diff --git a/.changeset/README.md b/.changeset/README.md deleted file mode 100644 index e5b6d8d6a67..00000000000 --- a/.changeset/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Changesets - -Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works -with multi-package repos, or single-package repos to help you version and publish your code. You can -find the full documentation for it [in our repository](https://github.com/changesets/changesets) - -We have a quick list of common questions to get you started engaging with this project in -[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) diff --git a/.changeset/config.json b/.changeset/config.json deleted file mode 100644 index 0765cca37fb..00000000000 --- a/.changeset/config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "https://unpkg.com/@changesets/config@2.2.0/schema.json", - "changelog": [ - "@changesets/changelog-github", - { "repo": "reactjs/react-docgen" } - ], - "commit": false, - "fixed": [], - "linked": [], - "access": "public", - "baseBranch": "main", - "updateInternalDependencies": "patch", - "ignore": [ - "@react-docgen-internal/benchmark", - "@react-docgen-internal/website" - ] -} diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 179b45db9a6..00000000000 --- a/.editorconfig +++ /dev/null @@ -1,15 +0,0 @@ -root = true - -[*] -end_of_line = lf -insert_final_newline = true -charset = utf-8 - -[*.{js,cjs,mjs,ts,tsx,mts,cts,mdx}] -indent_style = space -indent_size = 2 -#indent_style = tab - -[**.json] -indent_style = space -indent_size = 2 diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index e090ba84f8b..00000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -github: [danez] diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index a10a24703a3..00000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,117 +0,0 @@ -name: CI - -on: - push: - branches: - - main - - renovate/** - pull_request: - -permissions: {} - -env: - NODE_VERSION: 22 - -jobs: - tests: - strategy: - matrix: - node: ['20.9.0', '22', '23'] - os: ['ubuntu'] - include: - - os: macos - node: '22' - - os: windows - node: '22' - - name: Tests (Node.js v${{ matrix.node }}, ${{ matrix.os }}) - runs-on: ${{ matrix.os }}-latest - - steps: - - name: Checkout - uses: actions/checkout@v5 - - - name: Install pnpm - uses: pnpm/action-setup@v4 - - - name: Setup Node.js - uses: actions/setup-node@v5 - with: - node-version: ${{ matrix.node }} - cache: 'pnpm' - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Unit tests with coverage - if: '${{ matrix.node == env.NODE_VERSION }}' - run: pnpm test -- --coverage - - - name: Unit tests - if: '${{ matrix.node != env.NODE_VERSION }}' - run: pnpm test - - - name: Upload coverage - if: '${{ matrix.node == env.NODE_VERSION }}' - continue-on-error: true - uses: coverallsapp/github-action@v2 - with: - parallel: true - flag-name: test-${{ matrix.os }} - - finish: - needs: tests - if: ${{ always() }} - continue-on-error: true - runs-on: ubuntu-latest - steps: - - name: Close parallel build - uses: coverallsapp/github-action@v2 - with: - parallel-finished: true - - lint: - name: Lint - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v5 - - - name: Install pnpm - uses: pnpm/action-setup@v4 - - - name: Setup Node.js - uses: actions/setup-node@v5 - with: - node-version: ${{ env.NODE_VERSION }} - cache: 'pnpm' - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Lint - run: pnpm lint - - website: - name: Website test build - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v5 - - - name: Install pnpm - uses: pnpm/action-setup@v4 - - - name: Setup Node.js - uses: actions/setup-node@v5 - with: - node-version: ${{ env.NODE_VERSION }} - cache: 'pnpm' - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Build - run: pnpm exec nx run @react-docgen-internal/website:build diff --git a/.github/workflows/changesets.yml b/.github/workflows/changesets.yml deleted file mode 100644 index f10c4f56faa..00000000000 --- a/.github/workflows/changesets.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: Release - -on: - push: - branches: - - main - -concurrency: ${{ github.workflow }}-${{ github.ref }} - -permissions: - id-token: write - -jobs: - release: - name: Release - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v5 - with: - # Do not persist credentials so changesets can use the provided token - persist-credentials: false - - - name: Install pnpm - uses: pnpm/action-setup@v4 - - - name: Setup Node.js - uses: actions/setup-node@v5 - with: - node-version: 'lts/*' - cache: 'pnpm' - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Run Changesets - id: changesets - uses: changesets/action@v1 - with: - publish: pnpm changesets-release - version: pnpm changesets-version - title: Packages ready to publish - commit: Publish new versions - env: - GITHUB_TOKEN: ${{ secrets.CHANGESETS_TOKEN }} - NPM_TOKEN: ${{secrets.NPM_TOKEN}} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index 786b7c0f839..00000000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: 'CodeQL' - -on: - push: - branches: [main] - pull_request: - # The branches below must be a subset of the branches above - branches: [main] - schedule: - - cron: '43 16 * * 5' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - steps: - - name: Checkout repository - uses: actions/checkout@v5 - - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: 'javascript' - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: "/language:javascript" diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml deleted file mode 100644 index 07d14ce49b1..00000000000 --- a/.github/workflows/lock.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: 'Lock Threads' - -on: - schedule: - - cron: '36 4 * * 4' - workflow_dispatch: - -permissions: - issues: write - pull-requests: write - discussions: write - -concurrency: - group: lock - -jobs: - action: - runs-on: ubuntu-latest - steps: - - uses: dessant/lock-threads@v5 - with: - log-output: true diff --git a/.github/workflows/ossar-analysis.yml b/.github/workflows/ossar-analysis.yml deleted file mode 100644 index 212f25b6aad..00000000000 --- a/.github/workflows/ossar-analysis.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: OSSAR - -on: - push: - branches: [main] - pull_request: - # The branches below must be a subset of the branches above - branches: [main] - schedule: - - cron: '38 4 * * 1' - -permissions: - contents: read - -jobs: - OSSAR-Scan: - permissions: - contents: read # for actions/checkout to fetch code - security-events: write # for github/codeql-action/upload-sarif to upload SARIF results - runs-on: windows-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v5 - - - name: Run OSSAR - uses: github/ossar-action@v1 - id: ossar - - - name: Upload OSSAR results - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: ${{ steps.ossar.outputs.sarifFile }} diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 7a09e4c990e..00000000000 --- a/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -benchmark/suites/ -dist/ -**/node_modules/* -!**/__fixtures__/**/node_modules/* -.idea/ -coverage/ -.nx/cache -.nx/workspace-data -.cursor/rules/nx-rules.mdc -.github/instructions/nx.instructions.md diff --git a/.gitpod.yml b/.gitpod.yml deleted file mode 100644 index 320f7b51ffc..00000000000 --- a/.gitpod.yml +++ /dev/null @@ -1,6 +0,0 @@ -tasks: - - init: npm install -g pnpm && pnpm install -vscode: - extensions: - - dbaeumer.vscode-eslint - - esbenp.prettier-vscode diff --git a/.npmrc b/.npmrc deleted file mode 100644 index 75b9f7b1fd7..00000000000 --- a/.npmrc +++ /dev/null @@ -1,3 +0,0 @@ -auto-install-peers=true -link-workspace-packages=false -provenance=true diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 7be039621db..00000000000 --- a/.prettierignore +++ /dev/null @@ -1,6 +0,0 @@ -benchmark/suites/ -**/__fixtures__/ -**/dist/ -**/node_modules -/.nx/cache -/.nx/workspace-data \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 2f1be750f5b..00000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,30 +0,0 @@ -# Contributing to react-docgen -We want to make contributing to this project as easy and transparent as -possible. - -## Our Development Process -The majority of development on react-docgen will occur through GitHub. Accordingly, -the process for contributing will follow standard GitHub protocol. - -## Pull Requests -We actively welcome your pull requests. -1. Fork the repo and create your branch from `main`. -2. If you've added code that should be tested, add tests -3. If you've changed APIs, update the documentation. -4. Ensure the test suite passes. -5. Make sure your code lints and typechecks. -6. If you haven't already, complete the Contributor License Agreement ("CLA"). - -## Issues -We use GitHub issues to track public bugs. Please ensure your description is -clear and has sufficient instructions to be able to reproduce the issue. - -Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe -disclosure of security bugs. In those cases, please go through the process -outlined on that page and do not file a public issue. - -## License -react-docgen is [MIT licensed](https://github.com/reactjs/react-docgen/blob/master/LICENSE). - -By contributing to react-docgen, you agree that your contributions will be licensed -under its MIT license. diff --git a/LICENSE b/LICENSE deleted file mode 100644 index b96dcb0480a..00000000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) Facebook, Inc. and its affiliates. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index 41e1dec839f..00000000000 --- a/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# react-docgen - -[`react-docgen`](./packages/react-docgen/) is a highly customizable library that -extracts information from [React](https://reactjs.org/) components and returns -this information in a structured machine readable format from which -documentations can be generated. - -[`@react-docgen/cli`](./packages/react-docgen-cli/) is a cli wrapper around the -library allowing using `react-docgen` on the command line. - -## Typescript - -See [this issue](https://github.com/reactjs/react-docgen/issues/1005) about the status of TypeScript. - -## Documentation - -For version 5.x please checkout the -[README.md on the 5.x branch](https://github.com/reactjs/react-docgen/blob/5.x/README.md) - -For version 6.x and newer please visit -[react-docgen.dev](https://react-docgen.dev) - -## License - -This project is licensed under the MIT License. diff --git a/benchmark/index.mjs b/benchmark/index.mjs deleted file mode 100644 index 68408bf2844..00000000000 --- a/benchmark/index.mjs +++ /dev/null @@ -1,115 +0,0 @@ -import fs from 'fs'; -import path, { dirname } from 'path'; -import { fileURLToPath } from 'url'; -import Table from 'cli-table'; -import glob from 'fast-glob'; -import Benchmark from 'benchmark'; -import { parse } from '../packages/react-docgen/dist/main.js'; -import { parse as parse5 } from 'react-docgen5'; -import { parse as parse6 } from 'react-docgen6'; - -console.log(`Node: ${process.version}`); - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -const head = ['fixture', 'v5.4.3', 'v6.0.0', 'main']; - -process.stdout.write(`Preparing suites ... `); - -const suites = [ - { - name: 'react-bootstrap', - files: await glob('./suites/react-bootstrap/src/*.tsx', { - absolute: false, - cwd: __dirname, - }), - }, -]; - -const table = new Table({ - head, - style: { - head: ['bold'], - }, -}); - -if (!global.gc) { - console.error( - 'Garbage collection unavailable. Pass --expose-gc ' + - 'when launching node to enable forced garbage collection.', - ); - process.exit(); -} - -const preparedSuites = []; - -suites.forEach(({ name, files }) => { - const suite = new Benchmark.Suite(name); - - files.forEach((file) => { - const code = fs.readFileSync(path.join(__dirname, file), 'utf-8'); - const options = { filename: file, babelrc: false, configFile: false }; - const newOptions = { babelOptions: options }; - - try { - // warmup - parse(code, newOptions); - parse6(code, newOptions); - parse5(code, undefined, undefined, options); - global.gc(); - - preparedSuites.push({ - code, - options, - newOptions, - }); - } catch { - // ignore errors - } - }); - - suite.add('v5.4.3', () => { - for (const { code, options } of preparedSuites) { - parse5(code, undefined, undefined, options); - } - }); - suite.add('v6.0.0-alpha.4', () => { - for (const { code, newOptions } of preparedSuites) { - parse6(code, newOptions); - } - }); - suite.add('current', () => { - for (const { code, newOptions } of preparedSuites) { - parse(code, newOptions); - } - }); - const result = [suite.name]; - - suite.on('cycle', function (event) { - { - // separate scope so we can cleanup all this afterwards - const bench = event.target; - const factor = bench.hz < 100 ? 100 : 1; - const msg = `${Math.round(bench.hz * factor) / factor} ops/sec ±${ - Math.round(bench.stats.rme * 100) / 100 - }% (${Math.round(bench.stats.mean * 1000)}ms)`; - - result.push(msg); - } - global.gc(); - }); - suite.on('complete', function () { - process.stdout.write( - '-> Winner: ' + this.filter('fastest').map('name') + '\n', - ); - }); - - process.stdout.write(`Done\nRunning benchmark for ${suite.name} ... `); - global.gc(); - suite.run({ async: false }); - global.gc(); // gc is disabled so ensure we run it - table.push(result); -}); - -global.gc(); // gc is disabled so ensure we run it -console.log(table.toString()); diff --git a/benchmark/package.json b/benchmark/package.json deleted file mode 100644 index 60b38cfd15d..00000000000 --- a/benchmark/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "@react-docgen-internal/benchmark", - "version": "0.0.0", - "private": true, - "description": "Generate benchmarks for react-docgen", - "scripts": { - "setup": "rm -rf ./suites/react-bootstrap/ && git clone --depth=1 --branch=v2.7.0 https://github.com/react-bootstrap/react-bootstrap.git ./suites/react-bootstrap/", - "start": "node --expose-gc ./index.mjs", - "debug": "node --inspect-brk --expose-gc ./index.mjs" - }, - "license": "MIT", - "dependencies": { - "benchmark": "2.1.4", - "cli-table": "0.3.11", - "fast-glob": "3.3.3", - "microtime": "3.1.1", - "react-docgen5": "npm:react-docgen@5.4.3", - "react-docgen6": "npm:react-docgen@6.0.0" - } -} diff --git a/eslint.config.mjs b/eslint.config.mjs deleted file mode 100644 index 9804850cdcd..00000000000 --- a/eslint.config.mjs +++ /dev/null @@ -1,97 +0,0 @@ -import { globalIgnores } from 'eslint/config'; -import globals from 'globals'; -import js from '@eslint/js'; -import prettierRecommended from 'eslint-plugin-prettier/recommended'; -import tseslint from 'typescript-eslint'; - -export default tseslint.config([ - globalIgnores([ - 'benchmark/suites/', - '**/__fixtures__/', - '**/dist/', - '**/.nx/', - '**/coverage', - '**/node_modules', - ]), - js.configs.recommended, - { - files: ['**/*.js', '**/*.mjs', '**/*.cjs', '**/*.ts', '**/*.tsx'], - languageOptions: { - globals: { - ...globals.node, - }, - - ecmaVersion: 2022, - sourceType: 'module', - }, - - rules: { - 'no-shadow': 'error', - 'no-var': 'error', - - 'padding-line-between-statements': [ - 'error', - { - blankLine: 'always', - prev: '*', - next: 'return', - }, - { - blankLine: 'always', - prev: ['const', 'let', 'var'], - next: '*', - }, - { - blankLine: 'any', - prev: ['const', 'let', 'var'], - next: ['const', 'let', 'var'], - }, - { - blankLine: 'never', - prev: ['import'], - next: ['import'], - }, - ], - - 'prefer-const': 'error', - }, - }, - { - files: ['**/*.cjs'], - - languageOptions: { - ecmaVersion: 2022, - sourceType: 'script', - }, - - rules: { - strict: ['error', 'global'], - }, - }, - { - files: ['**/*.ts', '**/*.tsx'], - - extends: [ - tseslint.configs.recommended, - tseslint.configs.strict, - tseslint.configs.stylistic, - ], - - rules: { - 'no-shadow': 'off', - '@typescript-eslint/no-shadow': 'error', - - '@typescript-eslint/array-type': [ - 'error', - { - default: 'array-simple', - }, - ], - - '@typescript-eslint/consistent-type-imports': 'error', - '@typescript-eslint/no-non-null-assertion': 'off', - '@typescript-eslint/sort-type-constituents': 'error', - }, - }, - prettierRecommended, -]); diff --git a/index.html b/index.html new file mode 100644 index 00000000000..30f71bc9195 --- /dev/null +++ b/index.html @@ -0,0 +1,12 @@ + + + + Redirecting… + + +

Redirecting…

+ Click here if you are not redirected. + + diff --git a/nx.json b/nx.json deleted file mode 100644 index 37510e0d221..00000000000 --- a/nx.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "$schema": "./node_modules/nx/schemas/nx-schema.json", - "targetDefaults": { - "build": { - "dependsOn": ["^build"], - "outputs": ["{projectRoot}/dist"], - "cache": true - }, - "test": { - "dependsOn": ["build"], - "cache": true - } - }, - "namedInputs": { - "default": ["{projectRoot}/**/*", "sharedGlobals"], - "sharedGlobals": [ - "{workspaceRoot}/nx.json", - "{workspaceRoot}/package.json", - "{workspaceRoot}/pnpm-lock.yaml", - "{workspaceRoot}/tsconfig.base.json" - ], - "production": ["default"] - } -} diff --git a/package.json b/package.json deleted file mode 100644 index 948c46a9f1a..00000000000 --- a/package.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "private": true, - "engines": { - "node": "^20.9.0 || >=22", - "pnpm": ">=10.6.2" - }, - "scripts": { - "build": "nx run-many --target=build --exclude='@react-docgen-internal/*'", - "lint": "eslint . --flag unstable_config_lookup_from_file --report-unused-disable-directives --max-warnings=0", - "fix": "eslint . --flag unstable_config_lookup_from_file --fix --report-unused-disable-directives --max-warnings=0", - "test": "nx run-many --target=test --exclude='@react-docgen-internal/*' --output-style=stream", - "copy:changelog:react-docgen": "cp ./packages/react-docgen/CHANGELOG.md ./packages/website/src/pages/docs/release-notes/react-docgen.mdx", - "copy:changelog:cli": "cp ./packages/react-docgen-cli/CHANGELOG.md ./packages/website/src/pages/docs/release-notes/cli.mdx", - "changesets-release": "pnpm build && changeset publish", - "changesets-version": "changeset version && pnpm install --lockfile-only && pnpm copy:changelog:react-docgen && pnpm copy:changelog:cli" - }, - "license": "MIT", - "devDependencies": { - "@changesets/changelog-github": "0.5.1", - "@changesets/cli": "2.29.7", - "@eslint/eslintrc": "3.3.1", - "@eslint/js": "9.36.0", - "@types/node": "20.19.17", - "@vitest/coverage-v8": "3.2.4", - "cpy": "12.0.1", - "eslint": "9.36.0", - "eslint-config-next": "15.5.4", - "eslint-config-prettier": "10.1.8", - "eslint-plugin-prettier": "5.5.4", - "execa": "9.6.0", - "globals": "16.4.0", - "nx": "21.5.3", - "prettier": "3.6.2", - "prettier-plugin-tailwindcss": "0.6.14", - "rimraf": "6.0.1", - "tempy": "3.1.0", - "typescript": "5.9.2", - "typescript-eslint": "8.44.1", - "vitest": "3.2.4" - }, - "packageManager": "pnpm@10.17.1" -} diff --git a/packages/react-docgen-cli/CHANGELOG.md b/packages/react-docgen-cli/CHANGELOG.md deleted file mode 100644 index 8017500ff2a..00000000000 --- a/packages/react-docgen-cli/CHANGELOG.md +++ /dev/null @@ -1,508 +0,0 @@ -# Release Notes - -## 3.0.3 - -### Patch Changes - -- [`bdfdbac`](https://github.com/reactjs/react-docgen/commit/bdfdbaca3e798be18bab3b499e9b49003b7798d6) - Thanks [@danez](https://github.com/danez)! - update dependency commander to - v14.0.1 - -- [`bdfdbac`](https://github.com/reactjs/react-docgen/commit/bdfdbaca3e798be18bab3b499e9b49003b7798d6) - Thanks [@danez](https://github.com/danez)! - update dependency debug to v4.4.3 - -- [`bdfdbac`](https://github.com/reactjs/react-docgen/commit/bdfdbaca3e798be18bab3b499e9b49003b7798d6) - Thanks [@danez](https://github.com/danez)! - update dependency chalk to v5.6.2 - -## 3.0.2 - -### Patch Changes - -- [#1017](https://github.com/reactjs/react-docgen/pull/1017) - [`a818275`](https://github.com/reactjs/react-docgen/commit/a818275de1ba7e616d2ba45d0d2cde4f703b961f) - Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update - dependency chalk to v5.6.0 - -- Updated dependencies - [[`4c7dd9d`](https://github.com/reactjs/react-docgen/commit/4c7dd9d12ffdb3ac1d6f9663124cc43ec7fabb08)]: - - react-docgen@8.0.1 - -## 3.0.1 - -### Patch Changes - -- [#996](https://github.com/reactjs/react-docgen/pull/996) - [`a9b5ca3`](https://github.com/reactjs/react-docgen/commit/a9b5ca3f5411e876264db716fc4640ad9d4fb928) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - debug to v4.4.1 - -- [#1000](https://github.com/reactjs/react-docgen/pull/1000) - [`5cedd84`](https://github.com/reactjs/react-docgen/commit/5cedd84aaf38ec45a08fb673034e0d9ac03df81b) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - commander to v14 - -## 3.0.0 - -### Major Changes - -- [#942](https://github.com/reactjs/react-docgen/pull/942) - [`c3dfead`](https://github.com/reactjs/react-docgen/commit/c3dfead6b1cfdd57e34d1689c2b1d1334e9ef328) - Thanks [@danez](https://github.com/danez)! - Drop support for Node.js 16, 17, - 18, 19 and 21. - - With this `react-docgen` version Node.js support is: - - Node.js 20.9.0 or newer 20.x versions - - Node.js 22.0.0 or any newer version - -### Patch Changes - -- [#961](https://github.com/reactjs/react-docgen/pull/961) - [`5e2a332`](https://github.com/reactjs/react-docgen/commit/5e2a33202e101e55fc6b0640c1ff6686f8f92189) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - commander to v13 - -- [#979](https://github.com/reactjs/react-docgen/pull/979) - [`3486af5`](https://github.com/reactjs/react-docgen/commit/3486af5db316864824fa5f0d86d3a92335b0912f) - Thanks [@renovate](https://github.com/apps/renovate)! - Fix bug with loading - CommonJS files - -- Updated dependencies - [[`06c2fae`](https://github.com/reactjs/react-docgen/commit/06c2fae6f0d7f1aea3f23c2bf0dbfdc7b801ccb8), - [`c3dfead`](https://github.com/reactjs/react-docgen/commit/c3dfead6b1cfdd57e34d1689c2b1d1334e9ef328)]: - - react-docgen@8.0.0 - -## 2.0.6 - -### Patch Changes - -- Updated dependencies - [[`639bf37`](https://github.com/reactjs/react-docgen/commit/639bf3799bd74c46c2163841fefd9f3cc847dce9)]: - - react-docgen@7.1.1 - -## 2.0.5 - -### Patch Changes - -- [#960](https://github.com/reactjs/react-docgen/pull/960) - [`8b1c753`](https://github.com/reactjs/react-docgen/commit/8b1c753a353d1ff44c3eca6c5e391dec1198ab7e) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - chalk to v5.4.1 - -- [#958](https://github.com/reactjs/react-docgen/pull/958) - [`f5d644a`](https://github.com/reactjs/react-docgen/commit/f5d644a3041c227c4889059e787fcbaab57ec70e) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - chalk to v5.4.0 - -- [#954](https://github.com/reactjs/react-docgen/pull/954) - [`3c0cbb0`](https://github.com/reactjs/react-docgen/commit/3c0cbb0c2869488ac96291f1d491a93c8c1b5b06) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - debug to v4.4.0 - -- [#963](https://github.com/reactjs/react-docgen/pull/963) - [`972a1a3`](https://github.com/reactjs/react-docgen/commit/972a1a316affc8164ac957432b177bba09f1e667) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - fast-glob to v3.3.3 - -## 2.0.4 - -### Patch Changes - -- [#931](https://github.com/reactjs/react-docgen/pull/931) - [`a10dd0c`](https://github.com/reactjs/react-docgen/commit/a10dd0c782f053b648cf9bab2042a9d31245fc3d) - Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update - dependency debug to v4.3.5 - -- [`f723041`](https://github.com/reactjs/react-docgen/commit/f7230419af3680b9ed87a323c4fdf46ead667459) - Thanks [@renovate[bot]](https://github.com/renovate%5Bbot%5D)! - fix(deps): - update dependency debug to v4.3.6 - -- [#943](https://github.com/reactjs/react-docgen/pull/943) - [`ef85698`](https://github.com/reactjs/react-docgen/commit/ef8569863974599f51b9c9e1c4b9202144fe7607) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - debug to v4.3.7 - -- Updated dependencies - [[`3033ca0`](https://github.com/reactjs/react-docgen/commit/3033ca0908eb53f6ae2ee8a40eb4ef96840ff7ad)]: - - react-docgen@7.1.0 - -## 2.0.3 - -### Patch Changes - -- Updated dependencies - [[`afe8d02`](https://github.com/reactjs/react-docgen/commit/afe8d022d058a5d49c6fc144fb165c02f4a764d9)]: - - react-docgen@7.0.3 - -## 2.0.2 - -### Patch Changes - -- Updated dependencies - [[`64bf1aa`](https://github.com/reactjs/react-docgen/commit/64bf1aa078148b4d44f8634252e5b726e24b8ee5)]: - - react-docgen@7.0.2 - -## 2.0.1 - -### Patch Changes - -- [#869](https://github.com/reactjs/react-docgen/pull/869) - [`6b19e8a`](https://github.com/reactjs/react-docgen/commit/6b19e8a34744d4f3f5c93b96c1258796f440ede1) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - fast-glob to v3.3.2 - -- Updated dependencies - [[`2b51bbd`](https://github.com/reactjs/react-docgen/commit/2b51bbd47d14638ff98014a59f52c13a0c88abf9)]: - - react-docgen@7.0.1 - -## 2.0.0 - -### Major Changes - -- [#848](https://github.com/reactjs/react-docgen/pull/848) - [`dda8915`](https://github.com/reactjs/react-docgen/commit/dda8915ce9f8d5065372570d590405f2c2403bd8) - Thanks [@danez](https://github.com/danez)! - Drop support for Node.js - version 14. - - The minimum supported version is now 16.14.0 - -### Minor Changes - -- [`b0a46e7`](https://github.com/reactjs/react-docgen/commit/b0a46e7429f2a7449eebeff329753b25ac4226c9) - Thanks [@danez](https://github.com/danez)! - update dependency commander to - v11 - -### Patch Changes - -- [#859](https://github.com/reactjs/react-docgen/pull/859) - [`7dd2264`](https://github.com/reactjs/react-docgen/commit/7dd22646877d9a454f7809de5cbbb72499758916) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - commander to v11.1.0 - -- Updated dependencies - [[`82154c3`](https://github.com/reactjs/react-docgen/commit/82154c3b59bf22acf3068165f87b089138fdf7ae), - [`6312f2f`](https://github.com/reactjs/react-docgen/commit/6312f2f47b9f679b5bf923a30855e813193ed4af), - [`c01d1a0`](https://github.com/reactjs/react-docgen/commit/c01d1a00fdba76cea38eebc953fd3d2dd3f12fbd), - [`dda8915`](https://github.com/reactjs/react-docgen/commit/dda8915ce9f8d5065372570d590405f2c2403bd8), - [`62e692f`](https://github.com/reactjs/react-docgen/commit/62e692fcca6f3d17dcf81ce72f2db1a95b2d694b), - [`74b6680`](https://github.com/reactjs/react-docgen/commit/74b6680910037b1b4b64dd57769b652bf775675e), - [`0641700`](https://github.com/reactjs/react-docgen/commit/0641700e4425390c0fe50e216a71e5e18322ab3b), - [`40ebb00`](https://github.com/reactjs/react-docgen/commit/40ebb0010a7a380f89e0c79a4a937cf9a50a3245), - [`82154c3`](https://github.com/reactjs/react-docgen/commit/82154c3b59bf22acf3068165f87b089138fdf7ae), - [`3be404e`](https://github.com/reactjs/react-docgen/commit/3be404eee6c8fc7bd867fea9d1987b7f438107d6)]: - - react-docgen@7.0.0 - -## 1.0.4 - -### Patch Changes - -- Updated dependencies - [[`8ba9ac7`](https://github.com/reactjs/react-docgen/commit/8ba9ac74279c74f06803773a1dc5acc50376b5f3)]: - - react-docgen@6.0.4 - -## 1.0.3 - -### Patch Changes - -- Updated dependencies - [[`c3c16e3`](https://github.com/reactjs/react-docgen/commit/c3c16e30ad4cffa7304543ff4bef9b4f13a05683)]: - - react-docgen@6.0.3 - -## 1.0.2 - -### Patch Changes - -- [#812](https://github.com/reactjs/react-docgen/pull/812) - [`0f97ece`](https://github.com/reactjs/react-docgen/commit/0f97ece8ea9cd722b495db67843295b8846bb071) - Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update - dependency chalk to v5.3.0 - -- [#813](https://github.com/reactjs/react-docgen/pull/813) - [`7aa1e8e`](https://github.com/reactjs/react-docgen/commit/7aa1e8e24d0eb0a0cf36192aa5d00a4944f9844b) - Thanks [@renovate](https://github.com/apps/renovate)! - fix(deps): update - dependency fast-glob to v3.3.0 - -- Updated dependencies - [[`ddf4e20`](https://github.com/reactjs/react-docgen/commit/ddf4e20160c41685d81f7d5d8cf21eccb4b41529)]: - - react-docgen@6.0.2 - -## 1.0.1 - -### Patch Changes - -- Updated dependencies - [[`c7e2bd5`](https://github.com/reactjs/react-docgen/commit/c7e2bd5911d660b42bc3bc8b368a7b7cdcf980fd)]: - - react-docgen@6.0.1 - -## 1.0.0 - -### Major Changes - -- [#693](https://github.com/reactjs/react-docgen/pull/693) - [`3b28f6e`](https://github.com/reactjs/react-docgen/commit/3b28f6ee864fddbd872441035b21ad416ae7f417) - Thanks [@danez](https://github.com/danez)! - Introducing the new CLI package - `@react-docgen/cli` which was extracted from `react-docgen` and is a complete - rewrite. Compared to the old CLI these are some of the major differences: - - Does not support input via stdin anymore - - The path argument is now a glob - - `-x, --extension` was removed in favor of globs - - `-e, --exclude` was removed - - `-i, --ignore` now accepts a glob - - `--handler` added - - `--importer` added - - `--failOnWarning` added - - Check out https://react-docgen.dev/docs/getting-started/cli for the - documentation. - -- [#714](https://github.com/reactjs/react-docgen/pull/714) - [`80e4c74`](https://github.com/reactjs/react-docgen/commit/80e4c747c19d80081c162118f9c7110916fc27a0) - Thanks [@danez](https://github.com/danez)! - Renamed `--handlers` option to - `--handler`. This unifies all options to be singular. - -### Minor Changes - -- [#714](https://github.com/reactjs/react-docgen/pull/714) - [`80e4c74`](https://github.com/reactjs/react-docgen/commit/80e4c747c19d80081c162118f9c7110916fc27a0) - Thanks [@danez](https://github.com/danez)! - `--resolver` option can now be - used multiple times. - - If used multiple times the resolvers will be chained in the defined order and - all components from all resolvers will be used. - -- [#753](https://github.com/reactjs/react-docgen/pull/753) - [`217a005`](https://github.com/reactjs/react-docgen/commit/217a00513e2a6554a0ff22ad988fd539fc818921) - Thanks [@danez](https://github.com/danez)! - Add support for the - `FindAnnotatedDefinitionsResolver`. - - Can be used with - - ``` - react-docgen --resolver find-all-annotated-components - ``` - -### Patch Changes - -- [`ebd9130`](https://github.com/reactjs/react-docgen/commit/ebd9130a583ee3698623205d3393a79ed4ce057b) - Thanks [@danez](https://github.com/danez)! - Display the correct help info - when running `react-docgen --help` - -- [#782](https://github.com/reactjs/react-docgen/pull/782) - [`72ac984`](https://github.com/reactjs/react-docgen/commit/72ac9841f02f1f6b925247621bc5aa56d3ba4267) - Thanks [@renovate](https://github.com/apps/renovate)! - Update dependency - commander to v10.0.1 - -- [`050313d`](https://github.com/reactjs/react-docgen/commit/050313d47c3922276e4a06bcf38836f34f9558fb) - Thanks [@danez](https://github.com/danez)! - Correctly add LICENSE file to - published packages - -- [#792](https://github.com/reactjs/react-docgen/pull/792) - [`e0999e1`](https://github.com/reactjs/react-docgen/commit/e0999e155fed3b4b2915a26599f475d0884196ca) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - slash to v5.1.0 - -- [#783](https://github.com/reactjs/react-docgen/pull/783) - [`fc8a97c`](https://github.com/reactjs/react-docgen/commit/fc8a97c5fb552f5e4d2cbffced6c66f8729d23b6) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - slash to v5.0.1 - -- [#729](https://github.com/reactjs/react-docgen/pull/729) - [`5b281f4`](https://github.com/reactjs/react-docgen/commit/5b281f40d4958099d59dc7ce459742516589d0a4) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - commander to v10 - -- Updated dependencies - [[`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`8fe3dbf`](https://github.com/reactjs/react-docgen/commit/8fe3dbf510d4d66539bf09db227de5036c125f25), - [`d7a39af`](https://github.com/reactjs/react-docgen/commit/d7a39af7162c312daba2be428613cb378cce0727), - [`7c99f15`](https://github.com/reactjs/react-docgen/commit/7c99f156b1cc49da8bc78ca9c7e3bb2da215c49d), - [`dfc2f85`](https://github.com/reactjs/react-docgen/commit/dfc2f85ae10a668880ed64710a5acd714edf3bf7), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`0a2481d`](https://github.com/reactjs/react-docgen/commit/0a2481df6328bdbe46a01fb25ee9a0966ec023ca), - [`0a2481d`](https://github.com/reactjs/react-docgen/commit/0a2481df6328bdbe46a01fb25ee9a0966ec023ca), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`caae6bf`](https://github.com/reactjs/react-docgen/commit/caae6bf74ee292a513d6610350d5790c9d23f931), - [`80e4c74`](https://github.com/reactjs/react-docgen/commit/80e4c747c19d80081c162118f9c7110916fc27a0), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`e956802`](https://github.com/reactjs/react-docgen/commit/e956802a26700bb3f827a4500d9fc18a4eed6599), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`a684d82`](https://github.com/reactjs/react-docgen/commit/a684d8281044b3f8c8baecc9148cd4ef2b8fd409), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`cc94da2`](https://github.com/reactjs/react-docgen/commit/cc94da24fc9b2107c7e9df8c680a114038cbb16e), - [`98a1138`](https://github.com/reactjs/react-docgen/commit/98a113884a2227a89e5aede84ad48238e5f5c4f0), - [`80e4c74`](https://github.com/reactjs/react-docgen/commit/80e4c747c19d80081c162118f9c7110916fc27a0), - [`3b28f6e`](https://github.com/reactjs/react-docgen/commit/3b28f6ee864fddbd872441035b21ad416ae7f417), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`ea25b16`](https://github.com/reactjs/react-docgen/commit/ea25b16deb721a81e9937a307f88854e4b19f56d), - [`5a226ac`](https://github.com/reactjs/react-docgen/commit/5a226ac97882378790291cb67b1c0eee471f9def), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`1aa0249`](https://github.com/reactjs/react-docgen/commit/1aa0249f293784091260839377f8204eefb1da23), - [`0a2481d`](https://github.com/reactjs/react-docgen/commit/0a2481df6328bdbe46a01fb25ee9a0966ec023ca), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`050313d`](https://github.com/reactjs/react-docgen/commit/050313d47c3922276e4a06bcf38836f34f9558fb), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`5215bab`](https://github.com/reactjs/react-docgen/commit/5215babf11e9c8a672d86816d1250c1e54b22249), - [`f6e4fe7`](https://github.com/reactjs/react-docgen/commit/f6e4fe75560b1420388119131a8f49abe52757f6), - [`5215bab`](https://github.com/reactjs/react-docgen/commit/5215babf11e9c8a672d86816d1250c1e54b22249), - [`80e4c74`](https://github.com/reactjs/react-docgen/commit/80e4c747c19d80081c162118f9c7110916fc27a0), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`d4c27d4`](https://github.com/reactjs/react-docgen/commit/d4c27d482e6364c38af2f7c871071f475dc40393), - [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad), - [`e08e08d`](https://github.com/reactjs/react-docgen/commit/e08e08d6cd56c833fd123019639dca9d819cd7ab)]: - - react-docgen@6.0.0 - -## 1.0.0-rc.6 - -### Patch Changes - -- [#792](https://github.com/reactjs/react-docgen/pull/792) - [`e0999e1`](https://github.com/reactjs/react-docgen/commit/e0999e155fed3b4b2915a26599f475d0884196ca) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - slash to v5.1.0 - -- Updated dependencies - [[`7c99f15`](https://github.com/reactjs/react-docgen/commit/7c99f156b1cc49da8bc78ca9c7e3bb2da215c49d)]: - - react-docgen@6.0.0-rc.9 - -## 1.0.0-rc.5 - -### Patch Changes - -- Updated dependencies - [[`5a226ac`](https://github.com/reactjs/react-docgen/commit/5a226ac97882378790291cb67b1c0eee471f9def)]: - - react-docgen@6.0.0-rc.8 - -## 1.0.0-rc.4 - -### Patch Changes - -- [#782](https://github.com/reactjs/react-docgen/pull/782) - [`72ac984`](https://github.com/reactjs/react-docgen/commit/72ac9841f02f1f6b925247621bc5aa56d3ba4267) - Thanks [@renovate](https://github.com/apps/renovate)! - Update dependency - commander to v10.0.1 - -- [#783](https://github.com/reactjs/react-docgen/pull/783) - [`fc8a97c`](https://github.com/reactjs/react-docgen/commit/fc8a97c5fb552f5e4d2cbffced6c66f8729d23b6) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - slash to v5.0.1 - -- Updated dependencies - [[`0a2481d`](https://github.com/reactjs/react-docgen/commit/0a2481df6328bdbe46a01fb25ee9a0966ec023ca), - [`0a2481d`](https://github.com/reactjs/react-docgen/commit/0a2481df6328bdbe46a01fb25ee9a0966ec023ca), - [`a684d82`](https://github.com/reactjs/react-docgen/commit/a684d8281044b3f8c8baecc9148cd4ef2b8fd409), - [`0a2481d`](https://github.com/reactjs/react-docgen/commit/0a2481df6328bdbe46a01fb25ee9a0966ec023ca), - [`e08e08d`](https://github.com/reactjs/react-docgen/commit/e08e08d6cd56c833fd123019639dca9d819cd7ab)]: - - react-docgen@6.0.0-rc.7 - -## 1.0.0-beta.3 - -### Minor Changes - -- 217a005: Add support for the `FindAnnotatedDefinitionsResolver`. - - Can be used with - - ``` - react-docgen --resolver find-all-annotated-components - ``` - -### Patch Changes - -- Updated dependencies [dfc2f85] -- Updated dependencies [cc94da2] -- Updated dependencies [98a1138] - - react-docgen@6.0.0-beta.6 - -## 1.0.0-beta.2 - -### Major Changes - -- 80e4c74: Renamed `--handlers` option to `--handler`. This unifies all options - to be singular. - -### Minor Changes - -- 80e4c74: `--resolver` option can now be used multiple times. - - If used multiple times the resolvers will be chained in the defined order and - all components from all resolvers will be used. - -### Patch Changes - -- ebd9130: Display the correct help info when running `react-docgen --help` -- 050313d: Correctly add LICENSE file to published packages -- 5b281f4: update dependency commander to v10 -- Updated dependencies [8fe3dbf] -- Updated dependencies [d7a39af] -- Updated dependencies [80e4c74] -- Updated dependencies [e956802] -- Updated dependencies [80e4c74] -- Updated dependencies [ea25b16] -- Updated dependencies [1aa0249] -- Updated dependencies [050313d] -- Updated dependencies [5215bab] -- Updated dependencies [f6e4fe7] -- Updated dependencies [5215bab] -- Updated dependencies [80e4c74] - - react-docgen@6.0.0-beta.5 - -## 1.0.0-alpha.1 - -### Major Changes - -- 3b28f6e: Introducing the new CLI package `@react-docgen/cli` which was - extracted from `react-docgen` and is a complete rewrite. Compared to the old - CLI these are some of the major differences: - - Does not support input via stdin anymore - - The path argument is now a glob - - `-x, --extension` was removed in favor of globs - - `-e, --exclude` was removed - - `-i, --ignore` now accepts a glob - - `--handler` added - - `--importer` added - - `--failOnWarning` added - - Check out https://react-docgen.dev/docs/getting-started/cli/ for the - documentation. - -### Patch Changes - -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [caae6bf] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [3b28f6e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [96d6e9e] -- Updated dependencies [d4c27d4] -- Updated dependencies [96d6e9e] - - react-docgen@6.0.0-alpha.4 diff --git a/packages/react-docgen-cli/README.md b/packages/react-docgen-cli/README.md deleted file mode 100644 index cb6cdac294e..00000000000 --- a/packages/react-docgen-cli/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# @react-docgen/cli - -# Documentation - -Please visit https://react-docgen.dev/docs/getting-started/cli/ diff --git a/packages/react-docgen-cli/package.json b/packages/react-docgen-cli/package.json deleted file mode 100644 index 5c785f9ec88..00000000000 --- a/packages/react-docgen-cli/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "@react-docgen/cli", - "version": "3.0.3", - "description": "A CLI to extract information from React components for documentation generation.", - "repository": { - "type": "git", - "url": "https://github.com/reactjs/react-docgen.git", - "directory": "packages/react-docgen-cli" - }, - "type": "module", - "bin": { - "react-docgen": "dist/cli.js" - }, - "files": [ - "dist" - ], - "engines": { - "node": "^20.9.0 || >=22" - }, - "scripts": { - "build": "rimraf dist/ && tsc", - "test": "vitest run" - }, - "keywords": [ - "react", - "cli", - "documentation-generation" - ], - "author": { - "name": "Daniel Tschinder (http://github.com/danez)" - }, - "license": "MIT", - "dependencies": { - "chalk": "5.6.2", - "commander": "14.0.1", - "debug": "4.4.3", - "fast-glob": "3.3.3", - "react-docgen": "workspace:8.0.1", - "slash": "5.1.0" - }, - "devDependencies": { - "@types/debug": "4.1.12" - } -} diff --git a/packages/react-docgen-cli/src/cli.ts b/packages/react-docgen-cli/src/cli.ts deleted file mode 100755 index 392a87af26c..00000000000 --- a/packages/react-docgen-cli/src/cli.ts +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env node -import { program } from 'commander'; - -program - .name('react-docgen') - .helpOption(false) - .executableDir('./commands/') - .command('parse', 'Extract meta information from React components.', { - isDefault: true, - executableFile: 'parse/command.js', - }); - -program.parse(); diff --git a/packages/react-docgen-cli/src/commands/parse/command.ts b/packages/react-docgen-cli/src/commands/parse/command.ts deleted file mode 100644 index 6a53701d238..00000000000 --- a/packages/react-docgen-cli/src/commands/parse/command.ts +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env node -import glob from 'fast-glob'; -import debugFactory from 'debug'; -import { program } from 'commander'; -import { builtinHandlers, parse } from 'react-docgen'; -import { readFile } from 'fs/promises'; -import outputResult from './output/outputResult.js'; -import loadOptions from './options/loadOptions.js'; -import outputError from './output/outputError.js'; -import { resolve } from 'path'; -import slash from 'slash'; -import type { Documentation } from 'react-docgen'; -import { ResolverConfigs } from './options/loadResolvers.js'; - -const debug = debugFactory('react-docgen:cli'); - -const defaultIgnoreGlobs = [ - '**/node_modules/**', - '**/__tests__/**', - '**/__mocks__/**', -]; - -const defaultHandlers = Object.keys(builtinHandlers); -const defaultResolvers = ['find-exported-component']; - -function collect(value: string, previous: string[]): string[] { - if ( - !previous || - previous === defaultIgnoreGlobs || - previous === defaultHandlers || - previous === defaultResolvers - ) { - previous = []; - } - - const values = value.split(','); - - return previous.concat(values); -} - -interface CLIOptions { - defaultIgnores: boolean; - failOnWarning: boolean; - handler?: string[]; - ignore: string[]; - importer?: string; - out?: string; - pretty: boolean; - resolver?: string[]; -} - -program - .name('react-docgen-parse') - .description( - 'Extract meta information from React components.\n' + - 'Either specify a paths to files or a glob pattern that matches multiple files.', - ) - .option( - '-o, --out ', - 'Store extracted information in the specified file instead of printing to stdout. If the file exists it will be overwritten.', - ) - .option( - '-i, --ignore ', - 'Comma separated list of glob patterns which will ignore the paths that match. Can also be used multiple times.', - collect, - defaultIgnoreGlobs, - ) - .option( - '--no-default-ignores', - 'Do not ignore the node_modules, __tests__, and __mocks__ directories.', - ) - .option('--pretty', 'Print the output JSON pretty', false) - .option( - '--failOnWarning', - 'Fail with exit code 2 on react-docgen component warnings. This includes "no component found" and "multiple components found" warnings.', - false, - ) - .option( - '--resolver ', - `Built-in resolver config (${Object.values(ResolverConfigs).join( - ', ', - )}), package name or path to a module that exports a resolver. Can also be used multiple times. When used, no default handlers will be added.`, - collect, - defaultResolvers, - ) - .option( - '--importer ', - 'Built-in importer name (fsImport, ignoreImporter), package name or path to a module that exports an importer.', - 'fsImporter', - ) - .option( - '--handler ', - 'Comma separated list of handlers to use. Can also be used multiple times. When used, no default handlers will be added.', - collect, - defaultHandlers, - ) - .argument('', 'Can be globs or paths to files') - .action(async (globs: string[], input: CLIOptions) => { - const { - defaultIgnores, - failOnWarning, - handler, - ignore, - importer, - out: output, - pretty, - resolver, - } = input; - - let finalIgnores = ignore; - - // Push the default ignores unless the --no-default-ignore is set - if (defaultIgnores === true && ignore !== defaultIgnoreGlobs) { - finalIgnores.push(...defaultIgnoreGlobs); - } else if (defaultIgnores === false && ignore === defaultIgnoreGlobs) { - finalIgnores = []; - } - - const options = await loadOptions({ - handler, - importer, - resolver, - }); - // we use slash to convert windows backslashes to unix format so fast-glob works - const files = await glob(globs.map(slash), { - ignore: finalIgnores?.map((ignorePath) => { - ignorePath = ignorePath.trim(); - // If the ignore glob starts with a dot we need to resolve the path to an - // absolute path in order for it to work - if (ignorePath.startsWith('.')) { - ignorePath = resolve(process.cwd(), ignorePath); - } - - // we use slash to convert windows backslashes to unix format so fast-glob works - return slash(ignorePath); - }), - }); - const result: Record = {}; - let errorEncountered = false; - - await Promise.all( - files.map(async (path) => { - debug(`Reading file ${path}`); - const content = await readFile(path, 'utf-8'); - - try { - result[path] = parse(content, { - filename: path, - handlers: options.handlers, - importer: options.importer, - resolver: options.resolver, - }); - } catch (error) { - const isError = outputError(error as Error, path, { failOnWarning }); - - if (isError) { - errorEncountered = true; - } - } - }), - ); - if (!errorEncountered) { - await outputResult(result, { pretty, output }); - } - }); - -program.parse(); diff --git a/packages/react-docgen-cli/src/commands/parse/options/loadOptions.ts b/packages/react-docgen-cli/src/commands/parse/options/loadOptions.ts deleted file mode 100644 index 3f082a2792e..00000000000 --- a/packages/react-docgen-cli/src/commands/parse/options/loadOptions.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { Handler, Importer, Resolver } from 'react-docgen'; -import { builtinHandlers, builtinImporters } from 'react-docgen'; -import loadReactDocgenPlugin from './loadReactDocgenPlugin.js'; -import loadResolvers from './loadResolvers.js'; - -export default async function loadOptions(input: { - handler: string[] | undefined; - importer: string | undefined; - resolver: string[] | undefined; -}): Promise<{ - handlers: Handler[] | undefined; - importer: Importer | undefined; - resolver: Resolver | undefined; -}> { - const importer = - input.importer && input.importer.length !== 0 - ? await loadReactDocgenPlugin( - input.importer, - 'importer', - builtinImporters, - ) - : undefined; - - const handlers = input.handler - ? await Promise.all( - input.handler.map(async (handler) => { - return await loadReactDocgenPlugin( - handler, - 'handler', - builtinHandlers, - ); - }), - ) - : undefined; - - return { - handlers, - importer, - resolver: await loadResolvers(input.resolver), - }; -} diff --git a/packages/react-docgen-cli/src/commands/parse/options/loadReactDocgenPlugin.ts b/packages/react-docgen-cli/src/commands/parse/options/loadReactDocgenPlugin.ts deleted file mode 100644 index 37a0bc5a149..00000000000 --- a/packages/react-docgen-cli/src/commands/parse/options/loadReactDocgenPlugin.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { resolve } from 'path'; -import importFile from '../../../utils/importFile.js'; - -export default async function loadReactDocgenPlugin( - input: string, - name: string, - builtins?: Record, -): Promise { - if (builtins?.[input]) { - return builtins[input]!; - } - - const path = resolve(process.cwd(), input); - // Maybe it is local path or a package - const plugin: T | undefined = - (await importFile(path)) ?? (await importFile(input)); - - if (plugin) { - return plugin; - } - - throw new Error( - `Unknown ${name}: "${input}" is not a built-in ${name}, ` + - `not a package, and can not be found locally ("${path}")`, - ); -} diff --git a/packages/react-docgen-cli/src/commands/parse/options/loadResolvers.ts b/packages/react-docgen-cli/src/commands/parse/options/loadResolvers.ts deleted file mode 100644 index e9ec06303cb..00000000000 --- a/packages/react-docgen-cli/src/commands/parse/options/loadResolvers.ts +++ /dev/null @@ -1,61 +0,0 @@ -import type { Resolver } from 'react-docgen'; -import { builtinResolvers } from 'react-docgen'; -import loadReactDocgenPlugin from './loadReactDocgenPlugin.js'; - -const { ChainResolver } = builtinResolvers; - -export enum ResolverConfigs { - FindAll = 'find-all-components', - FindAllExported = 'find-all-exported-components', - FindAllAnnotatedComponents = 'find-all-annotated-components', - FindExported = 'find-exported-component', -} - -async function loadResolver(input: string): Promise { - if (input === ResolverConfigs.FindAll) { - return new builtinResolvers.FindAllDefinitionsResolver(); - } else if (input === ResolverConfigs.FindAllExported) { - return new builtinResolvers.FindExportedDefinitionsResolver(); - } else if (input === ResolverConfigs.FindAllAnnotatedComponents) { - return new builtinResolvers.FindAnnotatedDefinitionsResolver(); - } else if (input === ResolverConfigs.FindExported) { - return new builtinResolvers.FindExportedDefinitionsResolver({ - limit: 1, - }); - } - - const loadedResolver = await loadReactDocgenPlugin( - input, - 'resolver', - ); - - // Check if it is a class constructor - // If it is we do not know how to construct the resolver so error instead - if ( - typeof loadedResolver === 'function' && - loadedResolver.toString().startsWith('class ') - ) { - throw new Error( - `The provided resolver '${input}' is not a function or a class instance but instead a class.` + - ' To solve this please make sure to provide a path to a file that returns a class instance.', - ); - } - - return loadedResolver; -} - -export default async function loadResolvers( - input: string[] | undefined, -): Promise { - if (!input || input.length === 0) { - return; - } - - if (input.length > 1) { - return new ChainResolver(await Promise.all(input.map(loadResolver)), { - chainingLogic: ChainResolver.Logic.ALL, - }); - } - - return loadResolver(input[0]!); -} diff --git a/packages/react-docgen-cli/src/commands/parse/output/outputError.ts b/packages/react-docgen-cli/src/commands/parse/output/outputError.ts deleted file mode 100644 index 708ec76a78f..00000000000 --- a/packages/react-docgen-cli/src/commands/parse/output/outputError.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { relative } from 'path'; -import chalk from 'chalk'; - -function isReactDocgenError(error: NodeJS.ErrnoException): boolean { - return Boolean( - error instanceof Error && error.code?.startsWith('ERR_REACTDOCGEN'), - ); -} - -function outputReactDocgenError( - error: Error, - filePath: string, - { failOnWarning }: { failOnWarning: boolean }, -): boolean { - let label = 'WARNING'; - let color = chalk.yellow; - let log = console.warn; - let isError = false; - - if (failOnWarning && isReactDocgenError(error)) { - process.exitCode = 2; - isError = true; - label = 'ERROR'; - color = chalk.red; - log = console.error; - } - - log( - color( - `▶ ${label}: ${error.message} 👀\n in ${chalk.underline( - relative(process.cwd(), filePath), - )}\n`, - ), - ); - - return isError; -} - -export default function outputError( - error: Error, - filePath: string, - options: { failOnWarning: boolean }, -): boolean { - if (isReactDocgenError(error)) { - return outputReactDocgenError(error, filePath, options); - } else { - process.exitCode = 1; - console.error(error); - - return true; - } -} diff --git a/packages/react-docgen-cli/src/commands/parse/output/outputResult.ts b/packages/react-docgen-cli/src/commands/parse/output/outputResult.ts deleted file mode 100644 index 7b04191f972..00000000000 --- a/packages/react-docgen-cli/src/commands/parse/output/outputResult.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { writeFile } from 'fs/promises'; -import type { Documentation } from 'react-docgen'; - -export default async function outputResult( - documentation: Record, - { pretty = false, output }: { pretty: boolean; output: string | undefined }, -): Promise { - const result = JSON.stringify( - documentation, - undefined, - pretty ? 2 : undefined, - ); - - if (output) { - await writeFile(output, result, 'utf-8'); - } else { - process.stdout.write(result + '\n'); - } -} diff --git a/packages/react-docgen-cli/src/utils/importFile.ts b/packages/react-docgen-cli/src/utils/importFile.ts deleted file mode 100644 index c1a44c27a0d..00000000000 --- a/packages/react-docgen-cli/src/utils/importFile.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { createRequire } from 'module'; -import { pathToFileURL } from 'url'; - -const require = createRequire(import.meta.url); -const resolveOptions = { paths: [process.cwd()] }; - -export default async function importFile( - importSpecifier: string, -): Promise { - try { - const importedFile = await import( - // need to convert to file:// url as on windows absolute path strings do not work - pathToFileURL(require.resolve(importSpecifier, resolveOptions)).href - ); - - return importedFile.default ? importedFile.default : importedFile; - } catch (error) { - if ( - error instanceof Error && - (error as NodeJS.ErrnoException).code !== 'ERR_MODULE_NOT_FOUND' && - (error as NodeJS.ErrnoException).code !== 'MODULE_NOT_FOUND' - ) { - throw error; - } - - return undefined; - } -} diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/basic/Component.js b/packages/react-docgen-cli/tests/integration/__fixtures__/basic/Component.js deleted file mode 100644 index d35bc49b9b0..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/basic/Component.js +++ /dev/null @@ -1,9 +0,0 @@ -const React = require('react'); - -// @component -module.exports = class Component extends React.Component { - displayName = "Component" - - otherMethod() {} - render() {} -}; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/basic/NoComponent.js b/packages/react-docgen-cli/tests/integration/__fixtures__/basic/NoComponent.js deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-cjs/Component.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-cjs/Component.js deleted file mode 100644 index a3c7eb41603..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-cjs/Component.js +++ /dev/null @@ -1,10 +0,0 @@ -const React = require('react'); -import x from './other.cjs'; - -function Component() { - return
; -}; - -Component.displayName = x - -module.exports = Component diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-cjs/handler.cjs b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-cjs/handler.cjs deleted file mode 100644 index e9f492ec5cd..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-cjs/handler.cjs +++ /dev/null @@ -1,5 +0,0 @@ -const testHandler = function (documentation) { - documentation.set('displayName', 'testhandler'); -}; - -module.exports = testHandler; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-esm/Component.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-esm/Component.js deleted file mode 100644 index a3c7eb41603..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-esm/Component.js +++ /dev/null @@ -1,10 +0,0 @@ -const React = require('react'); -import x from './other.cjs'; - -function Component() { - return
; -}; - -Component.displayName = x - -module.exports = Component diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-esm/handler.mjs b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-esm/handler.mjs deleted file mode 100644 index 4c6b55a5dd6..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-esm/handler.mjs +++ /dev/null @@ -1,5 +0,0 @@ -const testHandler = function (documentation) { - documentation.set('displayName', 'testhandler'); -}; - -export default testHandler; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-npm/Component.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-npm/Component.js deleted file mode 100644 index a3c7eb41603..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-npm/Component.js +++ /dev/null @@ -1,10 +0,0 @@ -const React = require('react'); -import x from './other.cjs'; - -function Component() { - return
; -}; - -Component.displayName = x - -module.exports = Component diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-npm/node_modules/test-react-docgen-handler/index.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-npm/node_modules/test-react-docgen-handler/index.js deleted file mode 100644 index e9f492ec5cd..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-npm/node_modules/test-react-docgen-handler/index.js +++ /dev/null @@ -1,5 +0,0 @@ -const testHandler = function (documentation) { - documentation.set('displayName', 'testhandler'); -}; - -module.exports = testHandler; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-npm/node_modules/test-react-docgen-handler/package.json b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-npm/node_modules/test-react-docgen-handler/package.json deleted file mode 100644 index a92d0ff2c41..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-handler-npm/node_modules/test-react-docgen-handler/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "test-react-docgen-handler" -} diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/Component.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/Component.js deleted file mode 100644 index a3c7eb41603..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/Component.js +++ /dev/null @@ -1,10 +0,0 @@ -const React = require('react'); -import x from './other.cjs'; - -function Component() { - return
; -}; - -Component.displayName = x - -module.exports = Component diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/custom-importer-esm/Component.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/custom-importer-esm/Component.js deleted file mode 100644 index a3c7eb41603..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/custom-importer-esm/Component.js +++ /dev/null @@ -1,10 +0,0 @@ -const React = require('react'); -import x from './other.cjs'; - -function Component() { - return
; -}; - -Component.displayName = x - -module.exports = Component diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/custom-importer-esm/importer.mjs b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/custom-importer-esm/importer.mjs deleted file mode 100644 index 274ce883f7a..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/custom-importer-esm/importer.mjs +++ /dev/null @@ -1,15 +0,0 @@ -const testImporter = function (pa, n, file) { - const newFile = file.parse('("importer")', 'x.js'); - - let path; - newFile.traverse({ - Program(p) { - path = p; - p.stop(); - } - }); - - return path.get('body')[0].get('expression'); -}; - -export default testImporter; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/custom-importer-npm/Component.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/custom-importer-npm/Component.js deleted file mode 100644 index a3c7eb41603..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/custom-importer-npm/Component.js +++ /dev/null @@ -1,10 +0,0 @@ -const React = require('react'); -import x from './other.cjs'; - -function Component() { - return
; -}; - -Component.displayName = x - -module.exports = Component diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/custom-importer-npm/node_modules/test-react-docgen-importer/index.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/custom-importer-npm/node_modules/test-react-docgen-importer/index.js deleted file mode 100644 index d8c52d2585e..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/custom-importer-npm/node_modules/test-react-docgen-importer/index.js +++ /dev/null @@ -1,15 +0,0 @@ -const testImporter = function (pa, n, file) { - const newFile = file.parse('("importer")', 'x.js'); - - let path; - newFile.traverse({ - Program(p) { - path = p; - p.stop(); - } - }); - - return path.get('body')[0].get('expression'); -}; - -module.exports = testImporter; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/custom-importer-npm/node_modules/test-react-docgen-importer/package.json b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/custom-importer-npm/node_modules/test-react-docgen-importer/package.json deleted file mode 100644 index 65df75ff836..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/custom-importer-npm/node_modules/test-react-docgen-importer/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "test-react-docgen-importer" -} diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/importer.cjs b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/importer.cjs deleted file mode 100644 index cc56ed37ee4..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-cjs/importer.cjs +++ /dev/null @@ -1,15 +0,0 @@ -const testImporter = function (pa, n, file) { - const newFile = file.parse('("importer")', 'x.js'); - - let path; - newFile.traverse({ - Program(p) { - path = p; - p.stop(); - } - }); - - return path.get('body')[0].get('expression'); -}; - -module.exports = testImporter; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-esm/Component.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-esm/Component.js deleted file mode 100644 index a3c7eb41603..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-esm/Component.js +++ /dev/null @@ -1,10 +0,0 @@ -const React = require('react'); -import x from './other.cjs'; - -function Component() { - return
; -}; - -Component.displayName = x - -module.exports = Component diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-esm/importer.mjs b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-esm/importer.mjs deleted file mode 100644 index 274ce883f7a..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-esm/importer.mjs +++ /dev/null @@ -1,15 +0,0 @@ -const testImporter = function (pa, n, file) { - const newFile = file.parse('("importer")', 'x.js'); - - let path; - newFile.traverse({ - Program(p) { - path = p; - p.stop(); - } - }); - - return path.get('body')[0].get('expression'); -}; - -export default testImporter; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-npm/Component.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-npm/Component.js deleted file mode 100644 index a3c7eb41603..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-npm/Component.js +++ /dev/null @@ -1,10 +0,0 @@ -const React = require('react'); -import x from './other.cjs'; - -function Component() { - return
; -}; - -Component.displayName = x - -module.exports = Component diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-npm/node_modules/test-react-docgen-importer/index.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-npm/node_modules/test-react-docgen-importer/index.js deleted file mode 100644 index d8c52d2585e..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-npm/node_modules/test-react-docgen-importer/index.js +++ /dev/null @@ -1,15 +0,0 @@ -const testImporter = function (pa, n, file) { - const newFile = file.parse('("importer")', 'x.js'); - - let path; - newFile.traverse({ - Program(p) { - path = p; - p.stop(); - } - }); - - return path.get('body')[0].get('expression'); -}; - -module.exports = testImporter; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-npm/node_modules/test-react-docgen-importer/package.json b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-npm/node_modules/test-react-docgen-importer/package.json deleted file mode 100644 index 65df75ff836..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-importer-npm/node_modules/test-react-docgen-importer/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "test-react-docgen-importer" -} diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/Component.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/Component.js deleted file mode 100644 index 1a0ceba0d5f..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/Component.js +++ /dev/null @@ -1,8 +0,0 @@ -const React = require('react'); - -const Component = React.createClass({ - displayName: 'Component', - render: function () {}, -}); - -module.exports = Component; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/node_modules/test-react-docgen-resolver-class/index.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/node_modules/test-react-docgen-resolver-class/index.js deleted file mode 100644 index 559f79ff687..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/node_modules/test-react-docgen-resolver-class/index.js +++ /dev/null @@ -1,23 +0,0 @@ -const code = ` - ({ - displayName: 'Custom', - }) -`; - -const customResolver = class { - resolve(file) { - const newFile = file.parse(code, 'x.js'); - let path; - - newFile.traverse({ - Program(p) { - path = p; - p.stop(); - } - }); - - return [path.get('body')[0].get('expression')]; - } -} - -module.exports = customResolver; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/node_modules/test-react-docgen-resolver-class/package.json b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/node_modules/test-react-docgen-resolver-class/package.json deleted file mode 100644 index 8c629f16740..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/node_modules/test-react-docgen-resolver-class/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "test-react-docgen-resolver-class" -} diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/node_modules/test-react-docgen-resolver/index.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/node_modules/test-react-docgen-resolver/index.js deleted file mode 100644 index a55182ff122..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/node_modules/test-react-docgen-resolver/index.js +++ /dev/null @@ -1,23 +0,0 @@ -const code = ` - ({ - displayName: 'Custom', - }) -`; - -const customResolver = class { - resolve(file) { - const newFile = file.parse(code, 'x.js'); - let path; - - newFile.traverse({ - Program(p) { - path = p; - p.stop(); - } - }); - - return [path.get('body')[0].get('expression')]; - } -} - -module.exports = new customResolver(); diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/node_modules/test-react-docgen-resolver/package.json b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/node_modules/test-react-docgen-resolver/package.json deleted file mode 100644 index 8d3ed80b3d1..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/node_modules/test-react-docgen-resolver/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "test-react-docgen-resolver" -} diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/resolver.cjs b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/resolver.cjs deleted file mode 100644 index a55182ff122..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/resolver.cjs +++ /dev/null @@ -1,23 +0,0 @@ -const code = ` - ({ - displayName: 'Custom', - }) -`; - -const customResolver = class { - resolve(file) { - const newFile = file.parse(code, 'x.js'); - let path; - - newFile.traverse({ - Program(p) { - path = p; - p.stop(); - } - }); - - return [path.get('body')[0].get('expression')]; - } -} - -module.exports = new customResolver(); diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/resolver.mjs b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/resolver.mjs deleted file mode 100644 index 30b014dff87..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-class/resolver.mjs +++ /dev/null @@ -1,25 +0,0 @@ -const code = ` - ({ - displayName: 'Custom', - }) -`; - -const customResolver = class { - resolve(file) { - const newFile = file.parse(code, 'x.js'); - let path; - - newFile.traverse({ - Program(p) { - path = p; - p.stop(); - } - }); - - return [path.get('body')[0].get('expression')]; - } -} - -const resolver = new customResolver(); - -export default resolver; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-function/Component.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-function/Component.js deleted file mode 100644 index 1a0ceba0d5f..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-function/Component.js +++ /dev/null @@ -1,8 +0,0 @@ -const React = require('react'); - -const Component = React.createClass({ - displayName: 'Component', - render: function () {}, -}); - -module.exports = Component; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-function/node_modules/test-react-docgen-resolver/index.js b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-function/node_modules/test-react-docgen-resolver/index.js deleted file mode 100644 index 8fcf0e1763a..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-function/node_modules/test-react-docgen-resolver/index.js +++ /dev/null @@ -1,23 +0,0 @@ -const code = ` - ({ - displayName: 'Custom', - }) -`; - -const customResolver = function ( - file, -) { - const newFile = file.parse(code, 'x.js'); - let path; - - newFile.traverse({ - Program(p) { - path = p; - p.stop(); - } - }); - - return [path.get('body')[0].get('expression')]; -}; - -module.exports = customResolver; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-function/node_modules/test-react-docgen-resolver/package.json b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-function/node_modules/test-react-docgen-resolver/package.json deleted file mode 100644 index 8d3ed80b3d1..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-function/node_modules/test-react-docgen-resolver/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "name": "test-react-docgen-resolver" -} diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-function/resolver.cjs b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-function/resolver.cjs deleted file mode 100644 index 8fcf0e1763a..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-function/resolver.cjs +++ /dev/null @@ -1,23 +0,0 @@ -const code = ` - ({ - displayName: 'Custom', - }) -`; - -const customResolver = function ( - file, -) { - const newFile = file.parse(code, 'x.js'); - let path; - - newFile.traverse({ - Program(p) { - path = p; - p.stop(); - } - }); - - return [path.get('body')[0].get('expression')]; -}; - -module.exports = customResolver; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-function/resolver.mjs b/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-function/resolver.mjs deleted file mode 100644 index d1d89b17efa..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/custom-resolver-function/resolver.mjs +++ /dev/null @@ -1,23 +0,0 @@ -const code = ` - ({ - displayName: 'Custom', - }) -`; - -const customResolver = function ( - file, -) { - const newFile = file.parse(code, 'x.js'); - let path; - - newFile.traverse({ - Program(p) { - path = p; - p.stop(); - } - }); - - return [path.get('body')[0].get('expression')]; -}; - -export default customResolver; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/ignore/__mocks__/MockComponent.js b/packages/react-docgen-cli/tests/integration/__fixtures__/ignore/__mocks__/MockComponent.js deleted file mode 100644 index 0858c85792a..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/ignore/__mocks__/MockComponent.js +++ /dev/null @@ -1,8 +0,0 @@ -const React = require('react'); - -const Component = React.createClass({ - displayName: 'MockComponent', - render: function () {}, -}); - -module.exports = Component; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/ignore/__tests__/TestComponent.js b/packages/react-docgen-cli/tests/integration/__fixtures__/ignore/__tests__/TestComponent.js deleted file mode 100644 index de3324c137a..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/ignore/__tests__/TestComponent.js +++ /dev/null @@ -1,8 +0,0 @@ -const React = require('react'); - -const Component = React.createClass({ - displayName: 'TestComponent', - render: function () {}, -}); - -module.exports = Component; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/ignore/foo/FooComponent.js b/packages/react-docgen-cli/tests/integration/__fixtures__/ignore/foo/FooComponent.js deleted file mode 100644 index 4843f1e0d63..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/ignore/foo/FooComponent.js +++ /dev/null @@ -1,8 +0,0 @@ -const React = require('react'); - -const Component = React.createClass({ - displayName: 'FooComponent', - render: function () {}, -}); - -module.exports = Component; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/ignore/node_modules/NodeModulesComponent.js b/packages/react-docgen-cli/tests/integration/__fixtures__/ignore/node_modules/NodeModulesComponent.js deleted file mode 100644 index 8ee5d6b4f95..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/ignore/node_modules/NodeModulesComponent.js +++ /dev/null @@ -1,8 +0,0 @@ -const React = require('react'); - -const Component = React.createClass({ - displayName: 'NodeModulesComponent', - render: function () {}, -}); - -module.exports = Component; diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/multiple/MultipleComponents.js b/packages/react-docgen-cli/tests/integration/__fixtures__/multiple/MultipleComponents.js deleted file mode 100644 index 23ed1a0b4e0..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/multiple/MultipleComponents.js +++ /dev/null @@ -1,15 +0,0 @@ -const React = require('react'); - -exports.ComponentA = React.createClass({ - displayName: 'ComponentA', - render: function () { - // ... - }, -}); - -exports.ComponentB = React.createClass({ - displayName: 'ComponentB', - render: function () { - // ... - }, -}); diff --git a/packages/react-docgen-cli/tests/integration/__fixtures__/syntax-error/SyntaxError.js b/packages/react-docgen-cli/tests/integration/__fixtures__/syntax-error/SyntaxError.js deleted file mode 100644 index 8f7c4dfc85a..00000000000 --- a/packages/react-docgen-cli/tests/integration/__fixtures__/syntax-error/SyntaxError.js +++ /dev/null @@ -1 +0,0 @@ -module.exports {} diff --git a/packages/react-docgen-cli/tests/integration/cli-test.ts b/packages/react-docgen-cli/tests/integration/cli-test.ts deleted file mode 100644 index 17bafe1e8c9..00000000000 --- a/packages/react-docgen-cli/tests/integration/cli-test.ts +++ /dev/null @@ -1,213 +0,0 @@ -import { readFile } from 'fs/promises'; -import { join } from 'path'; -import { temporaryFile } from 'tempy'; -import { describe, expect, test } from 'vitest'; -import withFixture from './utils/withFixture'; - -describe('cli', () => { - describe('glob', () => { - test('reads files provided as command line arguments', async () => { - await withFixture('basic', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - join(dir, `Component.js`), - join(dir, `NoComponent.js`), - ]); - - expect(stderr).toContain('NoComponent.js'); - expect(stdout).toContain('Component.js'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('reads absolute globs provided as command line arguments', async () => { - await withFixture('basic', async ({ dir, run }) => { - const { stdout, stderr } = await run([`${dir}/*`]); - - expect(stderr).toContain('NoComponent.js'); - expect(stdout).toContain('Component.js'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('reads relative globs provided as command line arguments', async () => { - await withFixture('basic', async ({ run }) => { - const { stdout, stderr } = await run(['./*']); - - expect(stderr).toContain('NoComponent.js'); - expect(stdout).toContain('Component.js'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - }); - - describe('ignore', () => { - test('ignores files in node_modules, __tests__ and __mocks__ by default', async () => { - await withFixture('ignore', async ({ dir, run }) => { - const { stdout, stderr } = await run([`${dir}/**/*`]); - - expect(stderr).toBe(''); - expect(stdout).not.toContain('MockComponent.js'); - expect(stdout).not.toContain('TestComponent.js'); - expect(stdout).not.toContain('NodeModulesComponent.js'); - expect(stdout).toContain('FooComponent.js'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('can disable default ignores', async () => { - await withFixture('ignore', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--no-default-ignores', - `${dir}/**/*`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('MockComponent.js'); - expect(stdout).toContain('TestComponent.js'); - expect(stdout).toContain('NodeModulesComponent.js'); - expect(stdout).toContain('FooComponent.js'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('ignores directory defined by glob starting with star', async () => { - await withFixture('ignore', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--ignore=**/foo/**', - `${dir}/**/*`, - ]); - - expect(stderr).toBe(''); - expect(stdout).not.toContain('MockComponent.js'); - expect(stdout).not.toContain('TestComponent.js'); - expect(stdout).not.toContain('NodeModulesComponent.js'); - expect(stdout).not.toContain('FooComponent.js'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('ignores directory defined by relative path', async () => { - await withFixture('ignore', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--ignore', - './foo/**', - `${dir}/**/*`, - ]); - - expect(stderr).toBe(''); - expect(stdout).not.toContain('MockComponent.js'); - expect(stdout).not.toContain('TestComponent.js'); - expect(stdout).not.toContain('NodeModulesComponent.js'); - expect(stdout).not.toContain('FooComponent.js'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('ignores directory with shortcut defined by glob starting with star', async () => { - await withFixture('ignore', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '-i', - '**/foo/**', - `${dir}/**/*`, - ]); - - expect(stderr).toBe(''); - expect(stdout).not.toContain('MockComponent.js'); - expect(stdout).not.toContain('TestComponent.js'); - expect(stdout).not.toContain('NodeModulesComponent.js'); - expect(stdout).not.toContain('FooComponent.js'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('ignores directory with shortcut defined by relative path', async () => { - await withFixture('ignore', async ({ dir, run }) => { - const { stdout, stderr } = await run(['-i', './foo/**', `${dir}/**/*`]); - - expect(stderr).toBe(''); - expect(stdout).not.toContain('MockComponent.js'); - expect(stdout).not.toContain('TestComponent.js'); - expect(stdout).not.toContain('NodeModulesComponent.js'); - expect(stdout).not.toContain('FooComponent.js'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - }); - - describe('out', () => { - test('writes to a file if provided', async () => { - await withFixture('basic', async ({ dir, run }) => { - const outFile = temporaryFile(); - const { stdout, stderr } = await run([ - `--out=${outFile}`, - `${dir}/Component.js`, - ]); - - const writtenResult = await readFile(outFile, 'utf-8'); - - expect(stderr).toBe(''); - expect(writtenResult.length).toBeGreaterThan(4); - expect(() => JSON.parse(writtenResult)).not.toThrowError(); - expect(stdout).toBe(''); - }); - }); - - test('writes to a file if provided shortcut', async () => { - await withFixture('basic', async ({ dir, run }) => { - const outFile = temporaryFile(); - const { stdout, stderr } = await run([ - '-o', - outFile, - `${dir}/Component.js`, - ]); - - const writtenResult = await readFile(outFile, 'utf-8'); - - expect(stderr).toBe(''); - expect(writtenResult.length).toBeGreaterThan(4); - expect(() => JSON.parse(writtenResult)).not.toThrowError(); - expect(stdout).toBe(''); - }); - }); - }); - - describe('pretty', () => { - test('by default does not prettify output', async () => { - await withFixture('basic', async ({ dir, run }) => { - const { stdout, stderr } = await run([join(dir, `Component.js`)]); - - expect(stderr).toBe(''); - expect(stdout).not.toContain('\n'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('does prettify output', async () => { - await withFixture('basic', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--pretty', - join(dir, `Component.js`), - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('\n'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - }); - - describe('error', () => { - test('does exit with code 2 on warning', async () => { - await withFixture('basic', async ({ dir, run }) => { - const { stdout, stderr, exitCode } = await run([ - '--failOnWarning', - `${dir}/*`, - ]); - - expect(stderr).toContain('NoComponent'); - expect(stdout).toEqual(''); - expect(exitCode).toBe(2); - }); - }); - }); -}); diff --git a/packages/react-docgen-cli/tests/integration/handler-test.ts b/packages/react-docgen-cli/tests/integration/handler-test.ts deleted file mode 100644 index f37e3b5934d..00000000000 --- a/packages/react-docgen-cli/tests/integration/handler-test.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { join } from 'path'; -import { describe, expect, test } from 'vitest'; -import { builtinHandlers } from 'react-docgen'; -import withFixture from './utils/withFixture'; - -describe('handler', () => { - describe('accepts the names of builtin handlers', () => { - test.each(Object.keys(builtinHandlers))('%s', async (importer) => { - await withFixture('basic', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - `--handler=${importer}`, - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('Component'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - }); - - describe('multiple handlers', () => { - test('multiple handlers arguments', async () => { - await withFixture('basic', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - `--handler=displayNameHandler`, - `--handler=componentDocblockHandler`, - `--handler=componentMethodsHandler`, - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('"displayName":"Component"'); - expect(stdout).toContain('"description":""'); - expect(stdout).toContain('"name":"otherMethod"'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('multiple handlers comma separated', async () => { - await withFixture('basic', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - `--handler=displayNameHandler,componentDocblockHandler,componentMethodsHandler`, - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('"displayName":"Component"'); - expect(stdout).toContain('"description":""'); - expect(stdout).toContain('"name":"otherMethod"'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - }); - - describe('custom handlers', () => { - test('accepts an absolute local CommonJS path', async () => { - await withFixture('custom-handler-cjs', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - `--handler=${join(dir, 'handler.cjs')}`, - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('"displayName":"testhandler"'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts a relative local CommonJS path', async () => { - await withFixture('custom-handler-cjs', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--handler', - './handler.cjs', - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('"displayName":"testhandler"'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts an absolute local ESM path', async () => { - await withFixture('custom-handler-esm', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - `--handler=${join(dir, 'handler.mjs')}`, - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('"displayName":"testhandler"'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts a relative local ESM path', async () => { - await withFixture('custom-handler-esm', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--handler', - './handler.mjs', - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('"displayName":"testhandler"'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts a npm package', async () => { - await withFixture('custom-handler-npm', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--handler=test-react-docgen-handler', - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('"displayName":"testhandler"'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('throws error when not found', async () => { - await withFixture('basic', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--handler=does-not-exist', - `${dir}/Component.js`, - ]); - - expect(stderr).toContain('Unknown handler: "does-not-exist"'); - expect(stdout).toBe(''); - }); - }); - }); -}); diff --git a/packages/react-docgen-cli/tests/integration/importer-test.ts b/packages/react-docgen-cli/tests/integration/importer-test.ts deleted file mode 100644 index 19a59852dc3..00000000000 --- a/packages/react-docgen-cli/tests/integration/importer-test.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { join } from 'path'; -import { describe, expect, test } from 'vitest'; -import { builtinImporters } from 'react-docgen'; -import withFixture from './utils/withFixture'; - -describe('importer', () => { - describe('accepts the names of builtin importers', () => { - test.each(Object.keys(builtinImporters))('%s', async (importer) => { - await withFixture('basic', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - `--importer=${importer}`, - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('Component'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - }); - - describe('custom importer', () => { - test('accepts an absolute local CommonJS path', async () => { - await withFixture('custom-importer-cjs', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - `--importer=${join(dir, 'importer.cjs')}`, - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('"displayName":"importer"'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts a relative local CommonJS path', async () => { - await withFixture('custom-importer-cjs', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--importer', - './importer.cjs', - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('"displayName":"importer"'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts an absolute local ESM path', async () => { - await withFixture('custom-importer-esm', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - `--importer=${join(dir, 'importer.mjs')}`, - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('"displayName":"importer"'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts a relative local ESM path', async () => { - await withFixture('custom-importer-esm', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--importer', - './importer.mjs', - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('"displayName":"importer"'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts a npm package', async () => { - await withFixture('custom-importer-npm', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--importer=test-react-docgen-importer', - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('"displayName":"importer"'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('throws error when not found', async () => { - await withFixture('basic', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--importer=does-not-exist', - `${dir}/Component.js`, - ]); - - expect(stderr).toContain('Unknown importer: "does-not-exist"'); - expect(stdout).toBe(''); - }); - }); - }); -}); diff --git a/packages/react-docgen-cli/tests/integration/resolver-test.ts b/packages/react-docgen-cli/tests/integration/resolver-test.ts deleted file mode 100644 index 0d6fe8bae13..00000000000 --- a/packages/react-docgen-cli/tests/integration/resolver-test.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { join } from 'path'; -import { describe, expect, test } from 'vitest'; -import { ResolverConfigs } from '../../src/commands/parse/options/loadResolvers.js'; -import withFixture from './utils/withFixture'; - -describe('resolver', () => { - describe('accepts the names of builtin resolver configs', () => { - test.each(Object.values(ResolverConfigs))('%s', async (importer) => { - await withFixture('basic', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - `--resolver=${importer}`, - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('Component'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - }); - - describe('custom resolver', () => { - describe('function', () => { - test('accepts an absolute local CommonJS path', async () => { - await withFixture('custom-resolver-function', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - `--resolver=${join(dir, 'resolver.cjs')}`, - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('Custom'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts a relative local CommonJS path', async () => { - await withFixture('custom-resolver-function', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--resolver', - './resolver.cjs', - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('Custom'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts an absolute local ESM path', async () => { - await withFixture('custom-resolver-function', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - `--resolver=${join(dir, 'resolver.mjs')}`, - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('Custom'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts a relative local ESM path', async () => { - await withFixture('custom-resolver-function', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--resolver', - './resolver.mjs', - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('Custom'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts a npm package', async () => { - await withFixture('custom-resolver-function', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--resolver=test-react-docgen-resolver', - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('Custom'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - }); - describe('class', () => { - test('accepts an absolute local CommonJS path', async () => { - await withFixture('custom-resolver-class', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - `--resolver=${join(dir, 'resolver.cjs')}`, - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('Custom'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts a relative local CommonJS path', async () => { - await withFixture('custom-resolver-class', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--resolver', - './resolver.cjs', - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('Custom'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts an absolute local ESM path', async () => { - await withFixture('custom-resolver-class', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - `--resolver=${join(dir, 'resolver.mjs')}`, - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('Custom'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts a relative local ESM path', async () => { - await withFixture('custom-resolver-class', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--resolver', - './resolver.mjs', - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('Custom'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('accepts a npm package', async () => { - await withFixture('custom-resolver-class', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--resolver=test-react-docgen-resolver', - `${dir}/Component.js`, - ]); - - expect(stderr).toBe(''); - expect(stdout).toContain('Custom'); - expect(() => JSON.parse(stdout)).not.toThrowError(); - }); - }); - - test('throws if export is not a class instance', async () => { - await withFixture('custom-resolver-class', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--resolver=test-react-docgen-resolver-class', - `${dir}/Component.js`, - ]); - - expect(stderr).toContain( - "The provided resolver 'test-react-docgen-resolver-class' is not a function or a class instance but instead a class", - ); - expect(stdout).toBe(''); - }); - }); - }); - - test('throws error when not found', async () => { - await withFixture('basic', async ({ dir, run }) => { - const { stdout, stderr } = await run([ - '--resolver=does-not-exist', - `${dir}/Component.js`, - ]); - - expect(stderr).toContain('Unknown resolver: "does-not-exist"'); - expect(stdout).toBe(''); - }); - }); - }); -}); diff --git a/packages/react-docgen-cli/tests/integration/utils/withFixture.ts b/packages/react-docgen-cli/tests/integration/utils/withFixture.ts deleted file mode 100644 index ea401a02b58..00000000000 --- a/packages/react-docgen-cli/tests/integration/utils/withFixture.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { rm, stat } from 'fs/promises'; -import { dirname, join } from 'path'; -import type { ExecaError, ExecaReturnValue } from 'execa'; -import { execaNode } from 'execa'; -import copy from 'cpy'; -import { temporaryDirectory } from 'tempy'; -import { fileURLToPath } from 'url'; - -const __dir = dirname(fileURLToPath(import.meta.url)); - -const fixtureDir = join(__dir, '../__fixtures__'); -const cliBinary = join(__dir, '../../../dist/cli.js'); - -export default async function withFixture( - fixture: string, - callback: (api: { - dir: string; - run: ( - args: readonly string[], - ) => Promise<{ stdout: string; stderr: string; exitCode: number }>; - }) => Promise, -): Promise { - const tempDir = temporaryDirectory(); - - async function run( - args: readonly string[], - ): Promise> { - try { - return await execaNode(cliBinary, args, { - cwd: tempDir, - }); - } catch (error) { - return error as ExecaError; - } - } - - await stat(join(fixtureDir, fixture)); - - await copy(join(fixtureDir, fixture, '**/*'), tempDir, {}); - await callback({ dir: tempDir, run }); - await rm(tempDir, { force: true, recursive: true }); -} diff --git a/packages/react-docgen-cli/tsconfig.json b/packages/react-docgen-cli/tsconfig.json deleted file mode 100644 index d6e3d9b995d..00000000000 --- a/packages/react-docgen-cli/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "declaration": false, - "outDir": "./dist" - }, - "exclude": ["**/__tests__/**/*", "**/__mocks__/**/*"], - "include": ["src/**/*"] -} diff --git a/packages/react-docgen-cli/vitest.config.ts b/packages/react-docgen-cli/vitest.config.ts deleted file mode 100644 index 8fa82bbafb9..00000000000 --- a/packages/react-docgen-cli/vitest.config.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { defineConfig } from 'vitest/config'; - -export default defineConfig({ - test: { - name: 'cli', - include: ['**/__tests__/**/*-test.ts', '**/tests/integration/**/*-test.ts'], - testTimeout: 30_000, - deps: { - interopDefault: false, - }, - coverage: { - all: true, - include: ['src/**'], - provider: 'v8', - reporter: ['text', 'lcov'], - }, - }, -}); diff --git a/packages/react-docgen/CHANGELOG.md b/packages/react-docgen/CHANGELOG.md deleted file mode 100644 index 4451c7ff11d..00000000000 --- a/packages/react-docgen/CHANGELOG.md +++ /dev/null @@ -1,870 +0,0 @@ -# Release Notes - -## 8.0.1 - -### Patch Changes - -- [#1009](https://github.com/reactjs/react-docgen/pull/1009) - [`4c7dd9d`](https://github.com/reactjs/react-docgen/commit/4c7dd9d12ffdb3ac1d6f9663124cc43ec7fabb08) - Thanks [@danez](https://github.com/danez)! - Do not fail on new VoidPattern - type - -## 8.0.0 - -### Major Changes - -- [#942](https://github.com/reactjs/react-docgen/pull/942) - [`c3dfead`](https://github.com/reactjs/react-docgen/commit/c3dfead6b1cfdd57e34d1689c2b1d1334e9ef328) - Thanks [@danez](https://github.com/danez)! - Drop support for Node.js 16, 17, - 18, 19 and 21. - - With this `react-docgen` version Node.js support is: - - Node.js 20.9.0 or newer 20.x versions - - Node.js 22.0.0 or any newer version - -### Patch Changes - -- [#993](https://github.com/reactjs/react-docgen/pull/993) - [`06c2fae`](https://github.com/reactjs/react-docgen/commit/06c2fae6f0d7f1aea3f23c2bf0dbfdc7b801ccb8) - Thanks [@danez](https://github.com/danez)! - Fixed crash when classes with - private fields are used - -## 7.1.1 - -### Patch Changes - -- [#969](https://github.com/reactjs/react-docgen/pull/969) - [`639bf37`](https://github.com/reactjs/react-docgen/commit/639bf3799bd74c46c2163841fefd9f3cc847dce9) - Thanks [@christon88](https://github.com/christon88)! - Expose more TypeScript - types - -## 7.1.0 - -### Minor Changes - -- [#923](https://github.com/reactjs/react-docgen/pull/923) - [`3033ca0`](https://github.com/reactjs/react-docgen/commit/3033ca0908eb53f6ae2ee8a40eb4ef96840ff7ad) - Thanks [@rvetere](https://github.com/rvetere)! - Support generic types on - `React.forwardRef` calls. - - Example: - - `react-docgen` will now find `IButtonProps`. - - ```ts - export const FullWidthButton = forwardRef( - () => {}, - ); - ``` - -## 7.0.3 - -### Patch Changes - -- [#890](https://github.com/reactjs/react-docgen/pull/890) - [`afe8d02`](https://github.com/reactjs/react-docgen/commit/afe8d022d058a5d49c6fc144fb165c02f4a764d9) - Thanks [@danez](https://github.com/danez)! - Do not throw error when using - namespace specifiers in export statements - -## 7.0.2 - -### Patch Changes - -- [`64bf1aa`](https://github.com/reactjs/react-docgen/commit/64bf1aa078148b4d44f8634252e5b726e24b8ee5) - Thanks [@danez](https://github.com/danez)! - Fix handling of template literals - -## 7.0.1 - -### Patch Changes - -- [#870](https://github.com/reactjs/react-docgen/pull/870) - [`2b51bbd`](https://github.com/reactjs/react-docgen/commit/2b51bbd47d14638ff98014a59f52c13a0c88abf9) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - @types/doctrine to ^0.0.9 - -## 7.0.0 - -### Major Changes - -- [#846](https://github.com/reactjs/react-docgen/pull/846) - [`82154c3`](https://github.com/reactjs/react-docgen/commit/82154c3b59bf22acf3068165f87b089138fdf7ae) - Thanks [@danez](https://github.com/danez)! - `getTypeFromReactComponent` now - returns an array of paths to types instead of just one. This can appear when - multiple type definitions are found for a component, for example: - - ```ts - const Component: React.FC = (props: { some: string }) => {}; - ``` - - In this example both the `Props` definition as well as `{ some: string }` are - now found and used. - - Here is a simple diff to illustrate the change when using - `getTypeFromReactComponent`: - - ```diff - - const type = getTypeFromReactComponent(path) - - -if (type) { - +if (type.length > 0) { - // do smth - } - - ``` - -- [#848](https://github.com/reactjs/react-docgen/pull/848) - [`dda8915`](https://github.com/reactjs/react-docgen/commit/dda8915ce9f8d5065372570d590405f2c2403bd8) - Thanks [@danez](https://github.com/danez)! - Drop support for Node.js - version 14. - - The minimum supported version is now 16.14.0 - -- [#846](https://github.com/reactjs/react-docgen/pull/846) - [`62e692f`](https://github.com/reactjs/react-docgen/commit/62e692fcca6f3d17dcf81ce72f2db1a95b2d694b) - Thanks [@danez](https://github.com/danez)! - `resolveToValue` will not resolve - to `ImportDeclaration` anymore but instead to one of the possible specifiers - (`ImportSpecifier`, `ImportDefaultSpecifier` or `ImportNamespaceSpecifier`). - This gives better understanding to which specifier exactly `resolveToValue` - did resolve a NodePath to. - - Here is a possible easy fix for this in a code snippet that uses - `resolveToValue` - - ```diff - const resolved = resolveToValue(path); - - -if (resolved.isImportDeclaration()) { - +if (resolved.parentPath?.isImportDeclaration()) { - // do smth - } - ``` - -### Minor Changes - -- [#862](https://github.com/reactjs/react-docgen/pull/862) - [`40ebb00`](https://github.com/reactjs/react-docgen/commit/40ebb0010a7a380f89e0c79a4a937cf9a50a3245) - Thanks [@danez](https://github.com/danez)! - Support `PropsWithoutRef`, - `PropsWithRef` and `PropsWithChildren` in TypeScript. - - Component props are now detected correctly when these builtin types are used, - but they do currently not add any props to the documentation. - -- [#846](https://github.com/reactjs/react-docgen/pull/846) - [`82154c3`](https://github.com/reactjs/react-docgen/commit/82154c3b59bf22acf3068165f87b089138fdf7ae) - Thanks [@danez](https://github.com/danez)! - Add support for `React.FC` in - TypeScript. - -### Patch Changes - -- [`6312f2f`](https://github.com/reactjs/react-docgen/commit/6312f2f47b9f679b5bf923a30855e813193ed4af) - Thanks [@renovate[bot]](https://github.com/renovate%5Bbot%5D)! - update - dependency @types/doctrine to ^0.0.7 - -- [#846](https://github.com/reactjs/react-docgen/pull/846) - [`c01d1a0`](https://github.com/reactjs/react-docgen/commit/c01d1a00fdba76cea38eebc953fd3d2dd3f12fbd) - Thanks [@danez](https://github.com/danez)! - Fix detection of react class - components when super class is imported via named import. - -- [#861](https://github.com/reactjs/react-docgen/pull/861) - [`74b6680`](https://github.com/reactjs/react-docgen/commit/74b6680910037b1b4b64dd57769b652bf775675e) - Thanks [@renovate](https://github.com/apps/renovate)! - update dependency - @types/doctrine to ^0.0.8 - -- [#846](https://github.com/reactjs/react-docgen/pull/846) - [`0641700`](https://github.com/reactjs/react-docgen/commit/0641700e4425390c0fe50e216a71e5e18322ab3b) - Thanks [@danez](https://github.com/danez)! - Remove unnecessary call to - `resolveToValue` when trying to find props type from react components. - -- [#858](https://github.com/reactjs/react-docgen/pull/858) - [`3be404e`](https://github.com/reactjs/react-docgen/commit/3be404eee6c8fc7bd867fea9d1987b7f438107d6) - Thanks [@danez](https://github.com/danez)! - Fix detection of React.Children - with ESM imports - -## 6.0.4 - -### Patch Changes - -- [#838](https://github.com/reactjs/react-docgen/pull/838) - [`8ba9ac7`](https://github.com/reactjs/react-docgen/commit/8ba9ac74279c74f06803773a1dc5acc50376b5f3) - Thanks [@danez](https://github.com/danez)! - Support index types correctly in - flow - -## 6.0.3 - -### Patch Changes - -- [#830](https://github.com/reactjs/react-docgen/pull/830) - [`c3c16e3`](https://github.com/reactjs/react-docgen/commit/c3c16e30ad4cffa7304543ff4bef9b4f13a05683) - Thanks [@danez](https://github.com/danez)! - Fixed error with object and array - patterns in function signatures. - -## 6.0.2 - -### Patch Changes - -- [#810](https://github.com/reactjs/react-docgen/pull/810) - [`ddf4e20`](https://github.com/reactjs/react-docgen/commit/ddf4e20160c41685d81f7d5d8cf21eccb4b41529) - Thanks [@danez](https://github.com/danez)! - Read docblock in nested flow - object types and use them as descriptions - -## 6.0.1 - -### Patch Changes - -- [#806](https://github.com/reactjs/react-docgen/pull/806) - [`c7e2bd5`](https://github.com/reactjs/react-docgen/commit/c7e2bd5911d660b42bc3bc8b368a7b7cdcf980fd) - Thanks [@danez](https://github.com/danez)! - Make docblocks for assigned - methods be correctly detected. - -## 6.0.0 - -### Major Changes - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Rename `flowTypeHandler` to - `codeTypeHandler` because it handles Flow and TypeScript - -- [#719](https://github.com/reactjs/react-docgen/pull/719) - [`d7a39af`](https://github.com/reactjs/react-docgen/commit/d7a39af7162c312daba2be428613cb378cce0727) - Thanks [@danez](https://github.com/danez)! - Refactored - `resolveComponentDefinition` utility. - - Renamed to `findComponentDefinition` - - Removed named export `isComponentDefinition` - - The utility now does a lot more than previously, check out the commit to see - the changes in detail. - -- [#761](https://github.com/reactjs/react-docgen/pull/761) - [`dfc2f85`](https://github.com/reactjs/react-docgen/commit/dfc2f85ae10a668880ed64710a5acd714edf3bf7) - Thanks [@danez](https://github.com/danez)! - Renamed `propDocBlockHandler` to - `propDocblockHandler` for consistency - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Simplify - `resolveObjectValuesToArray` and remove type handling. None of the code that - was handling types was used. - -- [`caae6bf`](https://github.com/reactjs/react-docgen/commit/caae6bf74ee292a513d6610350d5790c9d23f931) - Thanks [@danez](https://github.com/danez)! - The return values of - `resolveObjectValuesToArray` are now in the order they are defined in the - source code. - -- [#744](https://github.com/reactjs/react-docgen/pull/744) - [`e956802`](https://github.com/reactjs/react-docgen/commit/e956802a26700bb3f827a4500d9fc18a4eed6599) - Thanks [@danez](https://github.com/danez)! - Removed match utility. - - The utility can be replaced by babel helpers and is not needed anymore. Also - using explicit checks like `path.isMemberExpression()` is better for type - safety and catching potential bugs. - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Migrate react-docgen to ES - modules. Please read - [this](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) - -- [#693](https://github.com/reactjs/react-docgen/pull/693) - [`3b28f6e`](https://github.com/reactjs/react-docgen/commit/3b28f6ee864fddbd872441035b21ad416ae7f417) - Thanks [@danez](https://github.com/danez)! - The CLI was removed from - `react-docgen` into its own package `@react-docgen/cli`. - - Check out https://react-docgen.dev/docs/getting-started/cli for the - documentation. - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - The main `parse` API had some - breaking changes. - - The arguments were changed from previously 5 to just 2. The following diff - illustrates how to migrate: - - ```diff - -parse(src, resolver, handlers, importer, options: { filename, ...babelOptions}) - +parse(src, { resolver, handlers, importer, filename, babelOptions: {} }) - ``` - - - The return type is now always an array, independent of the resolver, even if - only one component was found in the file. - -- [#786](https://github.com/reactjs/react-docgen/pull/786) - [`0a2481d`](https://github.com/reactjs/react-docgen/commit/0a2481df6328bdbe46a01fb25ee9a0966ec023ca) - Thanks [@danez](https://github.com/danez)! - Renamed the method `toObject` to - `build` in the DocumentationBuilder. - - This method might be used by integrations. - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Renamed some of the main exports - for clarity. - - Renamed `handlers` to `builtinHandlers` Renamed `resolver` to - `builtinResolvers` Renamed `importers` to `builtinImporters` - -- [#743](https://github.com/reactjs/react-docgen/pull/743) - [`5215bab`](https://github.com/reactjs/react-docgen/commit/5215babf11e9c8a672d86816d1250c1e54b22249) - Thanks [@danez](https://github.com/danez)! - Removed support for the - `@extends React.Component` annotation on react class components. - - Instead, you can use the new `@component` annotation or define your own - annotation by creating a custom `FindAnnotatedDefinitionsResolver` instance - -- [#714](https://github.com/reactjs/react-docgen/pull/714) - [`80e4c74`](https://github.com/reactjs/react-docgen/commit/80e4c747c19d80081c162118f9c7110916fc27a0) - Thanks [@danez](https://github.com/danez)! - Renamed and migrated built-in - resolvers to classes. - - `findAllComponentDefinitions` was renamed to `FindAllDefinitionsResolver` - and is now a class. - - ```diff - -const resolver = builtinResolvers.findAllComponentDefinitions - +const resolver = new builtinResolvers.FindAllDefinitionsResolver() - ``` - - - `findAllExportedComponentDefinitions` was renamed to - `FindExportedDefinitionsResolver` and is now a class. - - ```diff - -const resolver = builtinResolvers.findAllExportedComponentDefinitions - +const resolver = new builtinResolvers.FindExportedDefinitionsResolver() - ``` - - - `findExportedComponentDefinition` was removed. Use - `FindExportedDefinitionsResolver` with the `limit` option instead. - - > This is still the default resolver. - - ```diff - -const resolver = builtinResolvers.findExportedComponentDefinition - +const resolver = new builtinResolvers.FindExportedDefinitionsResolver({ limit: 1 }) - ``` - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Migrated to babel toolchain - - This is one of the big changes in this new version of react-docgen. It made - the code a lot more robust because there are now finally working TypeScript - types for the ASTs. - - Another benefit from this change is that react-docgen is now a lot faster. 🚀 - In some tests an improvement of nearly 50% was seen in comparison to - version 5. - -- [#707](https://github.com/reactjs/react-docgen/pull/707) - [`d4c27d4`](https://github.com/reactjs/react-docgen/commit/d4c27d482e6364c38af2f7c871071f475dc40393) - Thanks [@danez](https://github.com/danez)! - Improve performance of file - system importer. - - The file system importer now also caches the resolving of files in addition to - parsing files. If the importer is used in an environment where files do change - at runtime (like a watch command) then the caches will need to be cleared on - every file change. - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Changed the minimum Node.js - version to 14.18.0 - -### Minor Changes - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Add support for `.cts` and `.mts` - extension when using typescript - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Treat functions returning - `React.Children.map` as components - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Improve performance by creating - all visitors only once - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Support all possible kinds of - functions in the `displayNameHandler` - -- [#786](https://github.com/reactjs/react-docgen/pull/786) - [`0a2481d`](https://github.com/reactjs/react-docgen/commit/0a2481df6328bdbe46a01fb25ee9a0966ec023ca) - Thanks [@danez](https://github.com/danez)! - Export the type for the - DocumentationBuilder. - -- [#786](https://github.com/reactjs/react-docgen/pull/786) - [`0a2481d`](https://github.com/reactjs/react-docgen/commit/0a2481df6328bdbe46a01fb25ee9a0966ec023ca) - Thanks [@danez](https://github.com/danez)! - The types `NodePath` and - `babelTypes` are now exported. - - These types are useful when building integrations in TypeScript. - - `babelTypes` includes all types from `@babel/types`. - -- [#714](https://github.com/reactjs/react-docgen/pull/714) - [`80e4c74`](https://github.com/reactjs/react-docgen/commit/80e4c747c19d80081c162118f9c7110916fc27a0) - Thanks [@danez](https://github.com/danez)! - Add the new ChainResolver which - allows multiple resolvers to be chained. - - ```ts - import { builtinResolvers } from 'react-docgen'; - - const { ChainResolver } = builtinResolvers; - const resolver = new ChainResolver([resolver1, resolver2], { - chainingLogic: ChainResolver.Logic.ALL, // or ChainResolver.Logic.FIRST_FOUND, - }); - ``` - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Support all literal types in - typescript - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Support flow qualified type names - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Support class and function - declarations without identifier - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Support resolving of - destructuring in `resolveToValue` - -- [#714](https://github.com/reactjs/react-docgen/pull/714) - [`80e4c74`](https://github.com/reactjs/react-docgen/commit/80e4c747c19d80081c162118f9c7110916fc27a0) - Thanks [@danez](https://github.com/danez)! - Allow resolvers to be classes in - addition to functions. - - ```ts - import type { ResolverClass, ResolverFunction } from 'react-docgen'; - - // This was the only option until now - const functionResolver: ResolverFunction = (file: FileState) => { - //needs to return array of found components - }; - - // This is the new class resolver - class MyResolver implements ResolverClass { - resolve(file: FileState) { - //needs to return array of found components - } - } - - const classResolver = new MyResolver(); - ``` - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Improve performance drastically - by making changes to AST traversal - - Visitors are now pre-exploded and are cached in the module scope instead of - creating them on every call. This change brought the benchmark from 170ops/s - to 225ops/sec - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Add codes to errors to be able to - easily detect them - - There is a new export `ERROR_CODES` that contains all possible error codes. - The two errors that have codes right now are: - - `MISSING_DEFINITION`: No component found in a file - - `MULTIPLE_DEFINITIONS`: Multiple components found in one file - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Support handling - `useImperativeHandle` correctly - -- [#743](https://github.com/reactjs/react-docgen/pull/743) - [`5215bab`](https://github.com/reactjs/react-docgen/commit/5215babf11e9c8a672d86816d1250c1e54b22249) - Thanks [@danez](https://github.com/danez)! - Added a new resolver that finds - annotated components. This resolver is also enabled by default. - - To use this feature simply annotated a component with `@component`. - - ```ts - // @component - class MyComponent {} - ``` - -### Patch Changes - -- [#745](https://github.com/reactjs/react-docgen/pull/745) - [`8fe3dbf`](https://github.com/reactjs/react-docgen/commit/8fe3dbf510d4d66539bf09db227de5036c125f25) - Thanks [@danez](https://github.com/danez)! - Fix crash when using TypeScript - mapped types - -- [#789](https://github.com/reactjs/react-docgen/pull/789) - [`7c99f15`](https://github.com/reactjs/react-docgen/commit/7c99f156b1cc49da8bc78ca9c7e3bb2da215c49d) - Thanks [@danez](https://github.com/danez)! - Fix TypeScript types when strict - null checks are disabled - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Handle `React.forwardRef` calls - without a function - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Fixed the handling of some edge - cases in resolveToValue - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Remove trailing commas and - semicolons from raw values in the documentation - -- [#767](https://github.com/reactjs/react-docgen/pull/767) - [`a684d82`](https://github.com/reactjs/react-docgen/commit/a684d8281044b3f8c8baecc9148cd4ef2b8fd409) - Thanks [@danez](https://github.com/danez)! - Fix handling of `PropTypes.oneOf` - to handle unresolved imported values correctly - -- [#761](https://github.com/reactjs/react-docgen/pull/761) - [`cc94da2`](https://github.com/reactjs/react-docgen/commit/cc94da24fc9b2107c7e9df8c680a114038cbb16e) - Thanks [@danez](https://github.com/danez)! - Fix using react-docgen in - browsers - -- [#761](https://github.com/reactjs/react-docgen/pull/761) - [`98a1138`](https://github.com/reactjs/react-docgen/commit/98a113884a2227a89e5aede84ad48238e5f5c4f0) - Thanks [@danez](https://github.com/danez)! - Add `displayName` and - `description` to Documentation type - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Parse jsdoc comments for - TypeScript structs - -- [#748](https://github.com/reactjs/react-docgen/pull/748) - [`ea25b16`](https://github.com/reactjs/react-docgen/commit/ea25b16deb721a81e9937a307f88854e4b19f56d) - Thanks [@danez](https://github.com/danez)! - Handle cyclic references in - PropTypes `shape()` and `exact()` methods. - -- [#787](https://github.com/reactjs/react-docgen/pull/787) - [`5a226ac`](https://github.com/reactjs/react-docgen/commit/5a226ac97882378790291cb67b1c0eee471f9def) - Thanks [@danez](https://github.com/danez)! - Fix @babel/traverse import to - work in non ESM environments - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Correctly handle ObjectProperties - in `isReactComponentMethod` - -- [#747](https://github.com/reactjs/react-docgen/pull/747) - [`1aa0249`](https://github.com/reactjs/react-docgen/commit/1aa0249f293784091260839377f8204eefb1da23) - Thanks [@danez](https://github.com/danez)! - Handle `typeof import('...')` and - `typeof MyType.property` correctly in TypeScript - -- [`050313d`](https://github.com/reactjs/react-docgen/commit/050313d47c3922276e4a06bcf38836f34f9558fb) - Thanks [@danez](https://github.com/danez)! - Correctly add LICENSE file to - published packages - -- [`96d6e9e`](https://github.com/reactjs/react-docgen/commit/96d6e9e6003b92604781553f6910812c74c18dad) - Thanks [@danez](https://github.com/danez)! - Add support for TSAsExpressions - when trying to stringify expressions - -- [#720](https://github.com/reactjs/react-docgen/pull/720) - [`f6e4fe7`](https://github.com/reactjs/react-docgen/commit/f6e4fe75560b1420388119131a8f49abe52757f6) - Thanks [@renovate](https://github.com/apps/renovate)! - Update dependency - strip-indent to v4 - -- [#769](https://github.com/reactjs/react-docgen/pull/769) - [`e08e08d`](https://github.com/reactjs/react-docgen/commit/e08e08d6cd56c833fd123019639dca9d819cd7ab) - Thanks [@danez](https://github.com/danez)! - Correctly resolve the values in - an `Object.values()` call - -## 6.0.0-rc.9 - -### Patch Changes - -- [#789](https://github.com/reactjs/react-docgen/pull/789) - [`7c99f15`](https://github.com/reactjs/react-docgen/commit/7c99f156b1cc49da8bc78ca9c7e3bb2da215c49d) - Thanks [@danez](https://github.com/danez)! - Fix TypeScript types when strict - null checks are disabled - -## 6.0.0-rc.8 - -### Patch Changes - -- [#787](https://github.com/reactjs/react-docgen/pull/787) - [`5a226ac`](https://github.com/reactjs/react-docgen/commit/5a226ac97882378790291cb67b1c0eee471f9def) - Thanks [@danez](https://github.com/danez)! - Fix @babel/traverse import to - work in non ESM environments - -## 6.0.0-rc.7 - -### Major Changes - -- [#786](https://github.com/reactjs/react-docgen/pull/786) - [`0a2481d`](https://github.com/reactjs/react-docgen/commit/0a2481df6328bdbe46a01fb25ee9a0966ec023ca) - Thanks [@danez](https://github.com/danez)! - Renamed the method `toObject` to - `build` in the DocumentationBuilder. - - This method might be used by integrations. - -### Minor Changes - -- [#786](https://github.com/reactjs/react-docgen/pull/786) - [`0a2481d`](https://github.com/reactjs/react-docgen/commit/0a2481df6328bdbe46a01fb25ee9a0966ec023ca) - Thanks [@danez](https://github.com/danez)! - Export the type for the - DocumentationBuilder. - -- [#786](https://github.com/reactjs/react-docgen/pull/786) - [`0a2481d`](https://github.com/reactjs/react-docgen/commit/0a2481df6328bdbe46a01fb25ee9a0966ec023ca) - Thanks [@danez](https://github.com/danez)! - The types `NodePath` and - `babelTypes` are now exported. - - These types are useful when building integrations in TypeScript. - - `babelTypes` includes all types from `@babel/types`. - -### Patch Changes - -- [#767](https://github.com/reactjs/react-docgen/pull/767) - [`a684d82`](https://github.com/reactjs/react-docgen/commit/a684d8281044b3f8c8baecc9148cd4ef2b8fd409) - Thanks [@danez](https://github.com/danez)! - Fix handling of `PropTypes.oneOf` - to handle unresolved imported values correctly - -- [#769](https://github.com/reactjs/react-docgen/pull/769) - [`e08e08d`](https://github.com/reactjs/react-docgen/commit/e08e08d6cd56c833fd123019639dca9d819cd7ab) - Thanks [@danez](https://github.com/danez)! - Correctly resolve the values in - an `Object.values()` call - -## 6.0.0-beta.6 - -### Major Changes - -- dfc2f85: Rename `propDocBlockHandler` to `propDocblockHandler` for consistency - -### Patch Changes - -- cc94da2: Fix using react-docgen in browsers -- 98a1138: Add `displayName` and `description` to Documentation type - -## 6.0.0-beta.5 - -### Major Changes - -- d7a39af: Refactored `resolveComponentDefinition` utility. - - Renamed to `findComponentDefinition` - - Removed named export `isComponentDefinition` - - The utility now does a lot more than previously, check out the commit to see - the changes in detail. - -- e956802: Remove match utility. - - The utility can be replaced by babel helpers and is not needed anymore. Also - using explicit checks like `path.isMemberExpression()` is better for type - safety and catching potential bugs. - -- 5215bab: Removed support for the `@extends React.Component` annotation on - react class components. - - Instead you can use the new `@component` annotation. - -- 80e4c74: Renamed and migrated built-in resolvers to classes. - - `findAllComponentDefinitions` was renamed to `FindAllDefinitionsResolver` - and is now a class. - - ```diff - -const resolver = builtinResolvers.findAllComponentDefinitions - +const resolver = new builtinResolvers.FindAllDefinitionsResolver() - ``` - - - `findAllExportedComponentDefinitions` was renamed to - `FindExportedDefinitionsResolver` and is now a class. - - ```diff - -const resolver = builtinResolvers.findAllExportedComponentDefinitions - +const resolver = new builtinResolvers.FindExportedDefinitionsResolver() - ``` - - - `findExportedComponentDefinition` was removed. Use - `FindExportedDefinitionsResolver` with the `limit` option instead. - - > This is still the default resolver. - - ```diff - -const resolver = builtinResolvers.findExportedComponentDefinition - +const resolver = new builtinResolvers.FindExportedDefinitionsResolver({ limit: 1 }) - ``` - -### Minor Changes - -- 80e4c74: Add the new ChainResolver which allows multiple resolvers to be - chained. - - ```ts - import { builtinResolvers } from 'react-docgen'; - - const { ChainResolver } = builtinResolvers; - const resolver = new ChainResolver([resolver1, resolver2], { - chainingLogic: ChainResolver.Logic.ALL, // or ChainResolver.Logic.FIRST_FOUND, - }); - ``` - -- 80e4c74: Allow resolvers to be classes in addition to functions. - - ```ts - import type { ResolverClass, ResolverFunction } from 'react-docgen'; - - // This was the only option until now - const functionResolver: ResolverFunction = (file: FileState) => { - //needs to return array of found components - }; - - // This is the new class resolver - class MyResolver implements ResolverClass { - resolve(file: FileState) { - //needs to return array of found components - } - } - - const classResolver = new MyResolver(); - ``` - -- 5215bab: Added a new resolver that finds annotated components. This resolver - is also enabled by default. - - To use this feature simply annotated a component with `@component`. - - ```ts - // @component - class MyComponent {} - ``` - -### Patch Changes - -- 8fe3dbf: Fix crash when using TypeScript mapped types -- ea25b16: Handle cyclic references in PropTypes `shape()` and `exact()` - methods. -- 1aa0249: Handle `typeof import('...')` and `typeof MyType.property` correctly - in TypeScript -- 050313d: Correctly add LICENSE file to published packages -- f6e4fe7: Update dependency strip-indent to v4 - -## 6.0.0-alpha.4 - -### Major Changes - -- 96d6e9e: Rename `flowTypeHandler` to `codeTypeHandler` because it handles Flow - and TypeScript -- 96d6e9e: Simplify `resolveObjectValuesToArray` and remove type handling. None - of the code that was handling types was actually used. -- caae6bf: The return values of `resolveObjectValuesToArray` are now in the - order they are defined in the source code. -- 96d6e9e: Migrate react-docgen to ES modules. Please read - [this](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) -- 3b28f6e: The CLI was removed from `react-docgen` into its own package - `@react-docgen/cli`. - - Check out https://react-docgen.dev/docs/getting-started/cli/ for the - documentation. - -- 96d6e9e: Main `parse` API was changed - - The main API changed and now includes only 2 arguments. - - ```diff - -parse(src, resolver, handlers, importer, options) - +parse(src, { resolver, handlers, importer, ... }) - ``` - -- 96d6e9e: Renamed some of the main exports for clarity. - - Renamed `handlers` to `builtinHandlers` Renamed `resolver` to - `builtinResolvers` Renamed `importers` to `builtinImporters` - -- 96d6e9e: Migrated to babel toolchain - - This is one of the big changes in this new version of react-docgen. It made - the code a lot more robust because there are now finally working TypeScript - types for the ASTs. - - Another benefit from this change that react-docgen is now a lot faster. 🚀 In - some tests an improvement of nearly 50% was seen in comparison to version 5. - -- d4c27d4: Improve performance of file system importer. - - The file system importer now also caches resolving of files in addition to - parsing files. If the importer is used in an environment where files do change - at runtime (like a watch command) then the caches will need to be cleared on - every file change. - -- 96d6e9e: Changed the minimum Node.js version to 14.18.0 - -### Minor Changes - -- 96d6e9e: Add support for `.cts` and `.mts` extension when using typescript -- 96d6e9e: Treat functions returning `React.Children.map` as components -- 96d6e9e: Improve performance by creating all visitors only once -- 96d6e9e: Support all possible kinds of functions in the `displayNameHandler` -- 96d6e9e: Support all literal types in typescript -- 96d6e9e: Support flow qualified type names -- 96d6e9e: Support class and function declarations without identifier -- 96d6e9e: Support resolving of destructurings in `resolveToValue` -- 96d6e9e: Improve performance drastically by making changes to AST traversal - - Visitors are now pre-exploded and are cached in the module scope instead of - creating them on every call. This change brought the benchmark from 170ops/s - to 225ops/sec - -- 96d6e9e: Add codes to errors to be able to easily detect them - - There is a new export `ERROR_CODES` that contains all possible error codes. - The two errors that have codes right now are: - - `MISSING_DEFINITION`: No component found in file - - `MULTIPLE_DEFINITIONS`: Multiple components found in one files - -- 96d6e9e: Support handling `useImperativeHandle` correctly - -### Patch Changes - -- 96d6e9e: Handle `React.forwardRef` calls without a function -- 96d6e9e: Handle some edge cases in resolveToValue -- 96d6e9e: Remove trailing commas and semicolons from raw values in the - documentation -- 96d6e9e: Parse jsdoc comments for TypeScript structs -- 96d6e9e: Correctly handle ObjectProperties in `isReactComponentMethod` -- 96d6e9e: Add support for TSAsExpressions when trying to stringify expressions - -## [6.0.0-alpha.3](https://github.com/reactjs/react-docgen/compare/v6.0.0-alpha.2...v6.0.0-alpha.3) (2022-06-13) - -### Bug Fixes - -- Correctly detect index access types in typescript - ([#400](https://github.com/reactjs/react-docgen/issues/400)) - ([85ea6a5](https://github.com/reactjs/react-docgen/commit/85ea6a518c837e209043d9dac1505f60e8dd33b6)) -- Correctly handle ObjectTypeSpreadProperty in object type annotations - ([#593](https://github.com/reactjs/react-docgen/issues/593)) - ([395f338](https://github.com/reactjs/react-docgen/commit/395f338ab8aa3f1d9e1c0f5a81dadd0ce00eb7d5)) -- Fix typescript types for parsing - ([34c55ac](https://github.com/reactjs/react-docgen/commit/34c55ac1d663cc604f4f548018d78e02e081a797)) -- Fix wrong detection of forwardRef in combination with memo - ([#592](https://github.com/reactjs/react-docgen/issues/592)) - ([ea9cbeb](https://github.com/reactjs/react-docgen/commit/ea9cbebef13de11d591f175438e59b48dbb67025)) -- Handle ObjectTypeSpreadProperties which are not resolvable - ([4b8b721](https://github.com/reactjs/react-docgen/commit/4b8b721e6332185c0964a35329108ccdb64f8bb8)) -- Ignore methods in `Object.value()` calls - ([4fc5b21](https://github.com/reactjs/react-docgen/commit/4fc5b21d899990681287c8d9d70771b7361ec41e)) - -## [6.0.0-alpha.2](https://github.com/reactjs/react-docgen/compare/v6.0.0-alpha.1...v6.0.0-alpha.2) (2022-04-04) - -### Bug Fixes - -- Change folder name inside the npm package back to `dist`. - ([5f3da8c](https://github.com/reactjs/react-docgen/commit/5f3da8c892fd052db470d0a44d13c704eef4d011)) - There was no real reason to change this and happened during the TypeScript - migration. - -## 6.0.0-alpha.1 (2022-04-04) - -### Bug Fixes - -- Fix for expressionTo with Spread and Methods - ([5f3da8c](https://github.com/reactjs/react-docgen/commit/5f3da8c892fd052db470d0a44d13c704eef4d011)) -- Remove obsolete id check - ([66961d8](https://github.com/reactjs/react-docgen/commit/66961d868fb09cbf2a96ea5a4edec602602851b3)) -- Remove usage of ast-type builders - ([17c8a9c](https://github.com/reactjs/react-docgen/commit/17c8a9c123e0b699e96137e8714cd57fe6200e0c)) - -### Features - -- Migrate to TypeScript - ([7b35e6f](https://github.com/reactjs/react-docgen/commit/7b35e6f1336c6c606b194b2d0e70376e9c1c0a9d)) -- Remove building out of scope AST Nodes from resolveToValue - ([5bcf56c](https://github.com/reactjs/react-docgen/commit/5bcf56c6f7d2d8118adc1ed80573f2e3555455cb)) - -### BREAKING CHANGES - -- `resolveToValue` will not create a `MemberExpression` for targets ending in - destructuring. It will now simply resolve to the `Identifier` inside the - destructuring. Use new helper `isDestructuringAssignment` to further check - this identifier. -- The helpers `resolveObjectValuesToArray` and `resolveObjectKeysToArray` return - now `string[]` instead of a `NodePath` diff --git a/packages/react-docgen/package.json b/packages/react-docgen/package.json deleted file mode 100644 index 6391f875432..00000000000 --- a/packages/react-docgen/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "react-docgen", - "version": "8.0.1", - "description": "A library to extract information from React components for documentation generation.", - "repository": { - "type": "git", - "url": "https://github.com/reactjs/react-docgen.git", - "directory": "packages/react-docgen" - }, - "type": "module", - "browser": { - "./dist/importer/fsImporter.js": "./dist/importer/ignoreImporter.js", - "./src/importer/fsImporter.ts": "./src/importer/ignoreImporter.ts", - "./dist/importer/makeFsImporter.js": "./dist/importer/makeIgnoreImporter.js", - "./src/importer/makeFsImporter.ts": "./src/importer/makeIgnoreImporter.ts" - }, - "files": [ - "dist" - ], - "engines": { - "node": "^20.9.0 || >=22" - }, - "main": "dist/main.js", - "typings": "dist/main.d.ts", - "scripts": { - "build": "rimraf dist/ && tsc", - "test": "vitest run" - }, - "keywords": [ - "react", - "documentation", - "documentation-generation" - ], - "author": { - "name": "Felix Kling (http://github.com/fkling)" - }, - "contributors": [ - "Daniel Tschinder (http://github.com/danez)" - ], - "license": "MIT", - "dependencies": { - "@babel/core": "^7.28.0", - "@babel/traverse": "^7.28.0", - "@babel/types": "^7.28.2", - "@types/babel__core": "^7.20.5", - "@types/babel__traverse": "^7.20.7", - "@types/doctrine": "^0.0.9", - "@types/resolve": "^1.20.2", - "doctrine": "^3.0.0", - "resolve": "^1.22.1", - "strip-indent": "^4.0.0" - } -} diff --git a/packages/react-docgen/src/Documentation.ts b/packages/react-docgen/src/Documentation.ts deleted file mode 100644 index f6e63d759c5..00000000000 --- a/packages/react-docgen/src/Documentation.ts +++ /dev/null @@ -1,244 +0,0 @@ -export interface Documentation { - childContext?: Record; - composes?: string[]; - context?: Record; - description?: string; - displayName?: string; - methods?: MethodDescriptor[]; - props?: Record; -} - -export interface MethodParameter { - name: string; - description?: string; - optional: boolean; - type?: TypeDescriptor | null; -} - -export interface MethodReturn { - description?: string; - type: TypeDescriptor | undefined; -} - -export type MethodModifier = 'async' | 'generator' | 'get' | 'set' | 'static'; - -export interface MethodDescriptor { - name: string; - description?: string | null; - docblock: string | null; - modifiers: MethodModifier[]; - params: MethodParameter[]; - returns: MethodReturn | null; -} - -export interface PropTypeDescriptor { - name: - | 'any' - | 'array' - | 'arrayOf' - | 'bool' - | 'custom' - | 'element' - | 'elementType' - | 'enum' - | 'exact' - | 'func' - | 'instanceOf' - | 'node' - | 'number' - | 'object' - | 'objectOf' - | 'shape' - | 'string' - | 'symbol' - | 'union'; - value?: unknown; - raw?: string; - computed?: boolean; - // These are only needed for shape/exact types. - // Consider consolidating PropTypeDescriptor and PropDescriptor - description?: string; - required?: boolean; -} - -export interface DefaultValueDescriptor { - value: unknown; - computed: boolean; -} - -export interface BaseType { - required?: boolean; - nullable?: boolean; - alias?: string; -} - -export interface SimpleType extends BaseType { - name: string; - raw?: string; -} - -export interface LiteralType extends BaseType { - name: 'literal'; - value: string; -} - -export interface ElementsType extends BaseType { - name: string; - raw: string; - elements: Array>; -} - -export interface FunctionArgumentType { - name: string; - type?: TypeDescriptor; - rest?: boolean; -} - -export interface FunctionSignatureType extends BaseType { - name: 'signature'; - type: 'function'; - raw: string; - signature: { - arguments: Array>; - return?: TypeDescriptor; - }; -} - -export interface TSFunctionSignatureType extends FunctionSignatureType { - signature: { - arguments: Array>; - return?: TypeDescriptor; - this?: TypeDescriptor; - }; -} - -export interface ObjectSignatureType - extends BaseType { - name: 'signature'; - type: 'object'; - raw: string; - signature: { - properties: Array<{ - key: TypeDescriptor | string; - value: TypeDescriptor; - description?: string; - }>; - constructor?: TypeDescriptor; - }; -} - -export type TypeDescriptor = - | ElementsType - | LiteralType - | ObjectSignatureType - | SimpleType - | T; - -export interface PropDescriptor { - type?: PropTypeDescriptor; - flowType?: TypeDescriptor; - tsType?: TypeDescriptor; - required?: boolean; - defaultValue?: DefaultValueDescriptor; - description?: string; -} - -export default class DocumentationBuilder { - #props: Map; - #context: Map; - #childContext: Map; - #composes: Set; - #data: Map; - - constructor() { - this.#props = new Map(); - this.#context = new Map(); - this.#childContext = new Map(); - this.#composes = new Set(); - this.#data = new Map(); - } - - addComposes(moduleName: string): void { - this.#composes.add(moduleName); - } - - set(key: string, value: unknown): void { - this.#data.set(key, value); - } - - get(key: string): T | null; - get(key: string): unknown { - return this.#data.get(key); - } - - getPropDescriptor(propName: string): PropDescriptor { - let propDescriptor = this.#props.get(propName); - - if (!propDescriptor) { - this.#props.set(propName, (propDescriptor = {})); - } - - return propDescriptor; - } - - getContextDescriptor(propName: string): PropDescriptor { - let propDescriptor = this.#context.get(propName); - - if (!propDescriptor) { - this.#context.set(propName, (propDescriptor = {})); - } - - return propDescriptor; - } - - getChildContextDescriptor(propName: string): PropDescriptor { - let propDescriptor = this.#childContext.get(propName); - - if (!propDescriptor) { - this.#childContext.set(propName, (propDescriptor = {})); - } - - return propDescriptor; - } - - build(): Documentation { - const obj: Documentation = {}; - - for (const [key, value] of this.#data) { - // @ts-expect-error custom handlers can add any properties to Documentation - obj[key] = value; - } - - if (this.#props.size > 0) { - obj.props = {}; - for (const [propName, propDescriptor] of this.#props) { - if (Object.keys(propDescriptor).length > 0) { - obj.props[propName] = propDescriptor; - } - } - } - - if (this.#context.size > 0) { - obj.context = {}; - for (const [contextName, contextDescriptor] of this.#context) { - if (Object.keys(contextDescriptor).length > 0) { - obj.context[contextName] = contextDescriptor; - } - } - } - - if (this.#childContext.size > 0) { - obj.childContext = {}; - for (const [childContextName, childContextDescriptor] of this - .#childContext) { - obj.childContext[childContextName] = childContextDescriptor; - } - } - - if (this.#composes.size > 0) { - obj.composes = Array.from(this.#composes); - } - - return obj; - } -} diff --git a/packages/react-docgen/src/FileState.ts b/packages/react-docgen/src/FileState.ts deleted file mode 100644 index 239a533e673..00000000000 --- a/packages/react-docgen/src/FileState.ts +++ /dev/null @@ -1,93 +0,0 @@ -import type { HubInterface, Scope, Visitor } from '@babel/traverse'; -import babelTraverse, { NodePath } from '@babel/traverse'; -import type { File, Node, Program } from '@babel/types'; -import type { Importer, ImportPath } from './importer/index.js'; -import babelParse from './babelParser.js'; -import type { TransformOptions } from '@babel/core'; - -// Workaround while babel is not a proper ES module -const traverse = babelTraverse.default ?? (babelTraverse as never); - -export default class FileState { - opts: TransformOptions; - path: NodePath; - ast: File; - scope: Scope; - code: string; - - #importer: Importer; - - hub: HubInterface = { - // keep it for the usage in babel-core, ex: path.hub.file.opts.filename - file: this, - parse: this.parse.bind(this), - import: this.import.bind(this), - getCode: () => this.code, - getScope: () => this.scope, - addHelper: () => undefined, - buildError: ( - node: Node, - msg: string, - Error: new (message?: string) => E, - ): E & { node: Node } => { - const err = new Error(msg); - - (err as E & { node: Node }).node = node; - - return err as E & { node: Node }; - }, - }; - - constructor( - options: TransformOptions, - { code, ast, importer }: { code: string; ast: File; importer: Importer }, - ) { - this.opts = options; - this.code = code; - this.ast = ast; - this.#importer = importer; - - this.path = NodePath.get({ - hub: this.hub, - parentPath: null, - parent: this.ast, - container: this.ast, - key: 'program', - }).setContext() as NodePath; - this.scope = this.path.scope; - } - - /** - * Try to resolve and import the ImportPath with the `name` - */ - import(path: ImportPath, name: string): NodePath | null { - return this.#importer(path, name, this); - } - - /** - * Parse the content of a new file - * The `filename` is required so that potential imports inside the content can be correctly resolved and - * the correct babel config file could be loaded. `filename` needs to be an absolute path. - */ - parse(code: string, filename: string): FileState { - const newOptions = { ...this.opts, filename }; - // We need to build a new parser, because there might be a new - // babel config file in effect, so we need to load it - const ast = babelParse(code, newOptions); - - return new FileState(newOptions, { - ast, - code, - importer: this.#importer, - }); - } - - traverse(visitors: Visitor, state?: S): void; - traverse(visitors: Visitor): void; - /** - * Traverse the current file - */ - traverse(visitors: Visitor, state?: unknown): void { - traverse(this.ast, visitors, this.scope, state); - } -} diff --git a/packages/react-docgen/src/__mocks__/Documentation.ts b/packages/react-docgen/src/__mocks__/Documentation.ts deleted file mode 100644 index 35a7d20ab07..00000000000 --- a/packages/react-docgen/src/__mocks__/Documentation.ts +++ /dev/null @@ -1,15 +0,0 @@ -export default class Documentation { - [x: string]: unknown; - composes: string[] = []; - descriptors: Record = {}; - - getPropDescriptor(name: string): unknown { - return this.descriptors[name] || (this.descriptors[name] = {}); - } - addComposes(name: string): void { - this.composes.push(name); - } - set(key: string, value: unknown): void { - this[key] = value; - } -} diff --git a/packages/react-docgen/src/__mocks__/FileState.ts b/packages/react-docgen/src/__mocks__/FileState.ts deleted file mode 100644 index ccd22c0633a..00000000000 --- a/packages/react-docgen/src/__mocks__/FileState.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { file, program } from '@babel/types'; -import FileState from '../FileState.js'; - -export default class FileStateMock extends FileState { - constructor() { - super( - {}, - { - code: '', - ast: file(program([])), - importer: () => { - return null; - }, - }, - ); - } -} diff --git a/packages/react-docgen/src/__tests__/__snapshots__/main-test.ts.snap b/packages/react-docgen/src/__tests__/__snapshots__/main-test.ts.snap deleted file mode 100644 index d7f54074fe9..00000000000 --- a/packages/react-docgen/src/__tests__/__snapshots__/main-test.ts.snap +++ /dev/null @@ -1,156 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`main > Class definition > parses with custom handlers 1`] = ` -[ - { - "description": "Example component description", - }, -] -`; - -exports[`main > Class definition > parses with default resolver/handlers 1`] = ` -[ - { - "description": "Example component description", - "displayName": "ABC", - "methods": [], - "props": { - "foo": { - "defaultValue": { - "computed": false, - "value": "true", - }, - "description": "Example prop description", - "required": false, - "type": { - "name": "bool", - }, - }, - }, - }, -] -`; - -exports[`main > React.createClass > parses with custom handlers 1`] = ` -[ - { - "description": "Example component description", - }, -] -`; - -exports[`main > React.createClass > parses with default resolver/handlers 1`] = ` -[ - { - "description": "Example component description", - "displayName": "ABC", - "methods": [], - "props": { - "foo": { - "defaultValue": { - "computed": false, - "value": "true", - }, - "description": "Example prop description", - "required": false, - "type": { - "name": "bool", - }, - }, - }, - }, -] -`; - -exports[`main > Stateless Component definition: ArrowFunctionExpression > parses with custom handlers 1`] = ` -[ - { - "description": "Example component description", - }, -] -`; - -exports[`main > Stateless Component definition: ArrowFunctionExpression > parses with default resolver/handlers 1`] = ` -[ - { - "description": "Example component description", - "displayName": "ABC", - "methods": [], - "props": { - "foo": { - "defaultValue": { - "computed": false, - "value": "true", - }, - "description": "Example prop description", - "required": false, - "type": { - "name": "bool", - }, - }, - }, - }, -] -`; - -exports[`main > Stateless Component definition: FunctionDeclaration > parses with custom handlers 1`] = ` -[ - { - "description": "Example component description", - }, -] -`; - -exports[`main > Stateless Component definition: FunctionDeclaration > parses with default resolver/handlers 1`] = ` -[ - { - "description": "Example component description", - "displayName": "ABC", - "methods": [], - "props": { - "foo": { - "defaultValue": { - "computed": false, - "value": "true", - }, - "description": "Example prop description", - "required": false, - "type": { - "name": "bool", - }, - }, - }, - }, -] -`; - -exports[`main > Stateless Component definition: FunctionExpression > parses with custom handlers 1`] = ` -[ - { - "description": "Example component description", - }, -] -`; - -exports[`main > Stateless Component definition: FunctionExpression > parses with default resolver/handlers 1`] = ` -[ - { - "description": "Example component description", - "displayName": "ABC", - "methods": [], - "props": { - "foo": { - "defaultValue": { - "computed": false, - "value": "true", - }, - "description": "Example prop description", - "required": false, - "type": { - "name": "bool", - }, - }, - }, - }, -] -`; diff --git a/packages/react-docgen/src/__tests__/main-test.ts b/packages/react-docgen/src/__tests__/main-test.ts deleted file mode 100644 index 4e23ff182c2..00000000000 --- a/packages/react-docgen/src/__tests__/main-test.ts +++ /dev/null @@ -1,198 +0,0 @@ -import { builtinHandlers, parse, ERROR_CODES } from '../main.js'; -import { describe, expect, test } from 'vitest'; - -// TODO make fixtures out of them? -describe('main', () => { - function testMain(source: string) { - test('parses with default resolver/handlers', () => { - const docs = parse(source); - - expect(docs).toMatchSnapshot(); - }); - - test('parses with custom handlers', () => { - const docs = parse(source, { - handlers: [builtinHandlers.componentDocblockHandler], - }); - - expect(docs).toMatchSnapshot(); - }); - } - - describe('React.createClass', () => { - testMain(` - var React = require("react"); - var PropTypes = React.PropTypes; - - var defaultProps = { - foo: true, - }; - var propTypes = { - /** - * Example prop description - */ - foo: PropTypes.bool - }; - - /** - * Example component description - */ - var Component = React.createClass({ - displayName: 'ABC', - propTypes, - getDefaultProps: function() { - return defaultProps; - } - }); - module.exports = Component - `); - }); - - describe('Class definition', () => { - testMain(` - const React = require("react"); - const PropTypes = React.PropTypes; - - const defaultProps = { - foo: true, - }; - const propTypes = { - /** - * Example prop description - */ - foo: PropTypes.bool - }; - - /** - * Example component description - */ - export default class Component extends React.Component { - static propTypes = propTypes; - // ... - } - Component.defaultProps = defaultProps; - Component.displayName = 'ABC'; - `); - }); - - describe('Stateless Component definition: ArrowFunctionExpression', () => { - testMain(` - import React, {PropTypes} from "react"; - - const defaultProps = { - foo: true, - }; - const propTypes = { - /** - * Example prop description - */ - foo: PropTypes.bool - }; - - /** - * Example component description - */ - let Component = props =>
; - Component.displayName = 'ABC'; - Component.defaultProps = defaultProps; - Component.propTypes = propTypes; - - export default Component; - `); - }); - - describe('Stateless Component definition: FunctionDeclaration', () => { - testMain(` - import React, {PropTypes} from "react"; - - const defaultProps = { - foo: true, - }; - const propTypes = { - /** - * Example prop description - */ - foo: PropTypes.bool - }; - - /** - * Example component description - */ - function Component (props) { - return
; - } - - Component.displayName = 'ABC'; - Component.defaultProps = defaultProps; - Component.propTypes = propTypes; - - export default Component; - `); - }); - - describe('Stateless Component definition: FunctionExpression', () => { - testMain(` - import React, {PropTypes} from "react"; - - const defaultProps = { - foo: true, - }; - const propTypes = { - /** - * Example prop description - */ - foo: PropTypes.bool - }; - - /** - * Example component description - */ - let Component = function(props) { - return React.createElement('div', null); - } - - Component.displayName = 'ABC'; - Component.defaultProps = defaultProps; - Component.propTypes = propTypes; - - export default Component; - `); - }); - - describe('Stateless Component definition', () => { - test('is not so greedy', () => { - const source = ` - import React, {PropTypes} from "react"; - - /** - * Example component description - */ - let NotAComponent = function(props) { - let HiddenComponent = () => React.createElement('div', null); - - return 7; - } - - NotAComponent.displayName = 'ABC'; - NotAComponent.defaultProps = { - foo: true - }; - - NotAComponent.propTypes = { - /** - * Example prop description - */ - foo: PropTypes.bool - }; - - export default NotAComponent; - `; - - expect(() => parse(source)).toThrowError( - expect.objectContaining({ - code: ERROR_CODES.MISSING_DEFINITION, - }), - ); - }); - }); -}); diff --git a/packages/react-docgen/src/__tests__/parse-test.ts b/packages/react-docgen/src/__tests__/parse-test.ts deleted file mode 100644 index 80f3c8a314a..00000000000 --- a/packages/react-docgen/src/__tests__/parse-test.ts +++ /dev/null @@ -1,142 +0,0 @@ -import type { ObjectExpression } from '@babel/types'; -import fs from 'fs'; -import { temporaryDirectory } from 'tempy'; -import { parse as testParse, noopImporter } from '../../tests/utils'; -import parse from '../parse.js'; -import { describe, expect, test, vi } from 'vitest'; -import { ERROR_CODES } from '../error'; -import type { ComponentNodePath, ResolverClass } from '../resolver/index.js'; - -const createEmptyClassResolver = (path?: ComponentNodePath) => - new (class implements ResolverClass { - resolve = vi.fn(() => { - return path ? [path] : []; - }); - })(); - -const createEmptyFunctionResolver = (path?: ComponentNodePath) => - vi.fn(() => (path ? [path] : [])); - -describe('parse', () => { - describe.each([ - { name: 'function', createEmptyResolver: createEmptyFunctionResolver }, - { name: 'class', createEmptyResolver: createEmptyClassResolver }, - ])('with $name resolver', ({ createEmptyResolver }) => { - test('allows custom component definition resolvers', () => { - const path = testParse.expression('{foo: "bar"}'); - const resolver = createEmptyResolver(path); - const handler = vi.fn(); - - parse('//empty', { - resolver, - handlers: [handler], - importer: noopImporter, - babelOptions: {}, - }); - - expect( - typeof resolver === 'object' ? resolver.resolve : resolver, - ).toBeCalled(); - expect(handler.mock.calls[0][1]).toBe(path); - }); - - test('errors if component definition is not found', () => { - const resolver = createEmptyResolver(); - - expect(() => - parse('//empty', { - resolver, - handlers: [], - importer: noopImporter, - babelOptions: {}, - }), - ).toThrowError( - expect.objectContaining({ - code: ERROR_CODES.MISSING_DEFINITION, - }), - ); - expect( - typeof resolver === 'object' ? resolver.resolve : resolver, - ).toBeCalled(); - - expect(() => - parse('//empty', { - resolver, - handlers: [], - importer: noopImporter, - babelOptions: {}, - }), - ).toThrowError( - expect.objectContaining({ - code: ERROR_CODES.MISSING_DEFINITION, - }), - ); - expect( - typeof resolver === 'object' ? resolver.resolve : resolver, - ).toBeCalled(); - }); - - test('uses local babelrc', () => { - const dir = temporaryDirectory(); - - try { - // Write and empty babelrc to override the parser defaults - fs.writeFileSync(`${dir}/.babelrc`, '{}'); - - expect(() => - parse('const chained = () => a |> b', { - resolver: createEmptyResolver(), - handlers: [], - importer: noopImporter, - babelOptions: { - cwd: dir, - filename: `${dir}/component.js`, - }, - }), - ).toThrowError( - /.*Support for the experimental syntax 'pipelineOperator' isn't currently enabled.*/, - ); - } finally { - fs.unlinkSync(`${dir}/.babelrc`); - fs.rmdirSync(dir); - } - }); - - test('supports custom parserOptions with plugins', () => { - expect(() => - parse('const chained: Type = 1;', { - resolver: createEmptyResolver(), - handlers: [], - importer: noopImporter, - babelOptions: { - parserOpts: { - plugins: [ - // no flow - 'jsx', - ], - }, - }, - }), - ).toThrowError(/.*\(1:13\).*/); - }); - - test('supports custom parserOptions without plugins', () => { - expect(() => - parse('const chained: Type = 1;', { - resolver: createEmptyResolver(), - handlers: [], - importer: noopImporter, - babelOptions: { - parserOpts: { - allowSuperOutsideMethod: true, - }, - }, - }), - ).toThrowError( - expect.objectContaining({ - code: ERROR_CODES.MISSING_DEFINITION, - }), - ); - }); - }); -}); diff --git a/packages/react-docgen/src/babelParser.ts b/packages/react-docgen/src/babelParser.ts deleted file mode 100644 index 8c323c5a99c..00000000000 --- a/packages/react-docgen/src/babelParser.ts +++ /dev/null @@ -1,88 +0,0 @@ -import type { ParserOptions, TransformOptions } from '@babel/core'; -import { loadPartialConfig, parseSync } from '@babel/core'; -import type { File } from '@babel/types'; -import { extname } from 'path'; - -const TYPESCRIPT_EXTS = new Set(['.cts', '.mts', '.ts', '.tsx']); - -function getDefaultPlugins( - options: TransformOptions, -): NonNullable { - return [ - 'jsx', - options.filename && TYPESCRIPT_EXTS.has(extname(options.filename)) - ? 'typescript' - : 'flow', - 'asyncDoExpressions', - 'decimal', - ['decorators', { decoratorsBeforeExport: false }], - 'decoratorAutoAccessors', - 'destructuringPrivate', - 'doExpressions', - 'exportDefaultFrom', - 'functionBind', - 'importAssertions', - 'moduleBlocks', - 'partialApplication', - ['pipelineOperator', { proposal: 'minimal' }], - ['recordAndTuple', { syntaxType: 'bar' }], - 'regexpUnicodeSets', - 'throwExpressions', - ]; -} - -function buildPluginList( - options: TransformOptions, -): NonNullable { - let plugins: NonNullable = []; - - if (options.parserOpts?.plugins) { - plugins = [...options.parserOpts.plugins]; - } - - // Let's check if babel finds a config file for this source file - // If babel does find a config file we do not apply our defaults - const partialConfig = loadPartialConfig(options); - - if ( - plugins.length === 0 && - partialConfig && - !partialConfig.hasFilesystemConfig() - ) { - plugins = getDefaultPlugins(options); - } - - // Ensure that the estree plugin is never active - // TODO add test - return plugins.filter((plugin) => plugin !== 'estree'); -} - -function buildParserOptions(options: TransformOptions): ParserOptions { - const plugins = buildPluginList(options); - - return { - sourceType: 'unambiguous', - ...(options.parserOpts || {}), - plugins, - tokens: false, - }; -} - -export default function babelParser( - src: string, - options: TransformOptions = {}, -): File { - const parserOpts = buildParserOptions(options); - const opts: TransformOptions = { - ...options, - parserOpts, - }; - - const ast = parseSync(src, opts); - - if (!ast) { - throw new Error('Unable to parse source code.'); - } - - return ast as File; -} diff --git a/packages/react-docgen/src/config.ts b/packages/react-docgen/src/config.ts deleted file mode 100644 index 19eb6263210..00000000000 --- a/packages/react-docgen/src/config.ts +++ /dev/null @@ -1,79 +0,0 @@ -import type { TransformOptions } from '@babel/core'; -import type { Handler } from './handlers/index.js'; -import { - childContextTypeHandler, - codeTypeHandler, - componentDocblockHandler, - componentMethodsHandler, - componentMethodsJsDocHandler, - contextTypeHandler, - defaultPropsHandler, - displayNameHandler, - propDocblockHandler, - propTypeCompositionHandler, - propTypeHandler, -} from './handlers/index.js'; -import type { Importer } from './importer/index.js'; -import { fsImporter } from './importer/index.js'; -import type { Resolver } from './resolver/index.js'; -import { - ChainResolver, - FindAnnotatedDefinitionsResolver, - FindExportedDefinitionsResolver, -} from './resolver/index.js'; - -export interface Config { - handlers?: Handler[]; - importer?: Importer; - resolver?: Resolver; - /** - * shortcut for `babelOptions.filename` - * Set to an absolute path (recommended) to the file currently being parsed or - * to an relative path that is relative to the `babelOptions.cwd`. - */ - filename?: string; - babelOptions?: TransformOptions; -} -export type InternalConfig = Omit, 'filename'>; - -const defaultResolvers: Resolver[] = [ - new FindExportedDefinitionsResolver({ - limit: 1, - }), - new FindAnnotatedDefinitionsResolver(), -]; -const defaultResolver: Resolver = new ChainResolver(defaultResolvers, { - chainingLogic: ChainResolver.Logic.ALL, -}); -const defaultImporter: Importer = fsImporter; - -export const defaultHandlers: Handler[] = [ - propTypeHandler, - contextTypeHandler, - childContextTypeHandler, - propTypeCompositionHandler, - propDocblockHandler, - codeTypeHandler, - defaultPropsHandler, - componentDocblockHandler, - displayNameHandler, - componentMethodsHandler, - componentMethodsJsDocHandler, -]; - -export function createConfig(inputConfig: Config): InternalConfig { - const { babelOptions, filename, handlers, importer, resolver } = inputConfig; - - const config = { - babelOptions: { ...babelOptions }, - handlers: handlers ?? defaultHandlers, - importer: importer ?? defaultImporter, - resolver: resolver ?? defaultResolver, - }; - - if (filename) { - config.babelOptions.filename = filename; - } - - return config; -} diff --git a/packages/react-docgen/src/error.ts b/packages/react-docgen/src/error.ts deleted file mode 100644 index e6ff30686ed..00000000000 --- a/packages/react-docgen/src/error.ts +++ /dev/null @@ -1,21 +0,0 @@ -export enum ERROR_CODES { - MISSING_DEFINITION = 'ERR_REACTDOCGEN_MISSING_DEFINITION', - MULTIPLE_DEFINITIONS = 'ERR_REACTDOCGEN_MULTIPLE_DEFINITIONS', -} - -const messages = new Map([ - [ERROR_CODES.MISSING_DEFINITION, 'No suitable component definition found.'], - [ - ERROR_CODES.MULTIPLE_DEFINITIONS, - 'Multiple exported component definitions found.', - ], -]); - -export class ReactDocgenError extends Error { - code: string | undefined; - constructor(code: ERROR_CODES) { - super(messages.get(code)); - - this.code = code; - } -} diff --git a/packages/react-docgen/src/handlers/__tests__/__snapshots__/codeTypeHandler-test.ts.snap b/packages/react-docgen/src/handlers/__tests__/__snapshots__/codeTypeHandler-test.ts.snap deleted file mode 100644 index 4f074311341..00000000000 --- a/packages/react-docgen/src/handlers/__tests__/__snapshots__/codeTypeHandler-test.ts.snap +++ /dev/null @@ -1,1694 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`codeTypeHandler > TypeAlias (flow) > class definition for flow <0.53 > detects intersection types 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "Foo", - }, - { - "name": "Bar", - }, - ], - "name": "intersection", - "raw": "Foo & Bar", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition for flow <0.53 > detects types correctly 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": true, - }, - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, - "hal": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition for flow <0.53 > detects union types 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "elements": [ - { - "name": "literal", - "value": ""test"", - }, - { - "name": "literal", - "value": "1", - }, - { - "name": "literal", - "value": "true", - }, - ], - "name": "union", - "raw": ""test" | 1 | true", - }, - "required": true, - }, - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition for flow <0.53 > detects whether a prop is required 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": false, - }, - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition for flow <0.53 > ignores hash map entry 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": false, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition for flow <0.53 > special generic type annotations > unwraps $Exact<...> 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition for flow <0.53 > special generic type annotations > unwraps $ReadOnly<...> 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition with State > detects intersection types 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "Foo", - }, - { - "name": "Bar", - }, - ], - "name": "intersection", - "raw": "Foo & Bar", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition with State > detects types correctly 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": true, - }, - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, - "hal": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition with State > detects union types 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "elements": [ - { - "name": "literal", - "value": ""test"", - }, - { - "name": "literal", - "value": "1", - }, - { - "name": "literal", - "value": "true", - }, - ], - "name": "union", - "raw": ""test" | 1 | true", - }, - "required": true, - }, - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition with State > detects whether a prop is required 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": false, - }, - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition with State > ignores hash map entry 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": false, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition with State > special generic type annotations > unwraps $Exact<...> 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition with State > special generic type annotations > unwraps $ReadOnly<...> 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition with inline props > detects intersection types 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "Foo", - }, - { - "name": "Bar", - }, - ], - "name": "intersection", - "raw": "Foo & Bar", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition with inline props > detects types correctly 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": true, - }, - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, - "hal": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition with inline props > detects union types 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "elements": [ - { - "name": "literal", - "value": ""test"", - }, - { - "name": "literal", - "value": "1", - }, - { - "name": "literal", - "value": "true", - }, - ], - "name": "union", - "raw": ""test" | 1 | true", - }, - "required": true, - }, - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition with inline props > detects whether a prop is required 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": false, - }, - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition with inline props > ignores hash map entry 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": false, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition with inline props > special generic type annotations > unwraps $Exact<...> 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition with inline props > special generic type annotations > unwraps $ReadOnly<...> 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition without State > detects intersection types 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "Foo", - }, - { - "name": "Bar", - }, - ], - "name": "intersection", - "raw": "Foo & Bar", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition without State > detects types correctly 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": true, - }, - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, - "hal": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition without State > detects union types 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "elements": [ - { - "name": "literal", - "value": ""test"", - }, - { - "name": "literal", - "value": "1", - }, - { - "name": "literal", - "value": "true", - }, - ], - "name": "union", - "raw": ""test" | 1 | true", - }, - "required": true, - }, - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition without State > detects whether a prop is required 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": false, - }, - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition without State > ignores hash map entry 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": false, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition without State > special generic type annotations > unwraps $Exact<...> 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > class definition without State > special generic type annotations > unwraps $ReadOnly<...> 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > stateless component > detects intersection types 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "Foo", - }, - { - "name": "Bar", - }, - ], - "name": "intersection", - "raw": "Foo & Bar", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > stateless component > detects types correctly 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": true, - }, - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, - "hal": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > stateless component > detects union types 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "elements": [ - { - "name": "literal", - "value": ""test"", - }, - { - "name": "literal", - "value": "1", - }, - { - "name": "literal", - "value": "true", - }, - ], - "name": "union", - "raw": ""test" | 1 | true", - }, - "required": true, - }, - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > stateless component > detects whether a prop is required 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": false, - }, - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > stateless component > ignores hash map entry 1`] = ` -{ - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": false, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > stateless component > special generic type annotations > unwraps $Exact<...> 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (flow) > stateless component > special generic type annotations > unwraps $ReadOnly<...> 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition with State > detects intersection types 1`] = ` -{ - "foo": { - "description": "", - "required": true, - "tsType": { - "elements": [ - { - "name": "Foo", - }, - { - "name": "Bar", - }, - ], - "name": "intersection", - "raw": "Foo & Bar", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition with State > detects types correctly 1`] = ` -{ - "bar": { - "description": "", - "required": true, - "tsType": { - "name": "number", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, - "hal": { - "description": "", - "required": true, - "tsType": { - "name": "boolean", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition with State > detects union types 1`] = ` -{ - "bar": { - "description": "", - "required": true, - "tsType": { - "elements": [ - { - "name": "literal", - "value": ""test"", - }, - { - "name": "literal", - "value": "1", - }, - { - "name": "literal", - "value": "true", - }, - ], - "name": "union", - "raw": ""test" | 1 | true", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition with State > detects whether a prop is required 1`] = ` -{ - "bar": { - "description": "", - "required": false, - "tsType": { - "name": "number", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition with State > ignores hash map entry 1`] = ` -{ - "bar": { - "description": "", - "required": false, - "tsType": { - "name": "number", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition with State > special generic type annotations > unwraps $Exact<...> 1`] = `{}`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition with State > special generic type annotations > unwraps $ReadOnly<...> 1`] = `{}`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition with inline props > detects intersection types 1`] = ` -{ - "foo": { - "description": "", - "required": true, - "tsType": { - "elements": [ - { - "name": "Foo", - }, - { - "name": "Bar", - }, - ], - "name": "intersection", - "raw": "Foo & Bar", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition with inline props > detects types correctly 1`] = ` -{ - "bar": { - "description": "", - "required": true, - "tsType": { - "name": "number", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, - "hal": { - "description": "", - "required": true, - "tsType": { - "name": "boolean", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition with inline props > detects union types 1`] = ` -{ - "bar": { - "description": "", - "required": true, - "tsType": { - "elements": [ - { - "name": "literal", - "value": ""test"", - }, - { - "name": "literal", - "value": "1", - }, - { - "name": "literal", - "value": "true", - }, - ], - "name": "union", - "raw": ""test" | 1 | true", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition with inline props > detects whether a prop is required 1`] = ` -{ - "bar": { - "description": "", - "required": false, - "tsType": { - "name": "number", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition with inline props > ignores hash map entry 1`] = ` -{ - "bar": { - "description": "", - "required": false, - "tsType": { - "name": "number", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition with inline props > special generic type annotations > unwraps $Exact<...> 1`] = `{}`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition with inline props > special generic type annotations > unwraps $ReadOnly<...> 1`] = `{}`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition without State > detects intersection types 1`] = ` -{ - "foo": { - "description": "", - "required": true, - "tsType": { - "elements": [ - { - "name": "Foo", - }, - { - "name": "Bar", - }, - ], - "name": "intersection", - "raw": "Foo & Bar", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition without State > detects types correctly 1`] = ` -{ - "bar": { - "description": "", - "required": true, - "tsType": { - "name": "number", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, - "hal": { - "description": "", - "required": true, - "tsType": { - "name": "boolean", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition without State > detects union types 1`] = ` -{ - "bar": { - "description": "", - "required": true, - "tsType": { - "elements": [ - { - "name": "literal", - "value": ""test"", - }, - { - "name": "literal", - "value": "1", - }, - { - "name": "literal", - "value": "true", - }, - ], - "name": "union", - "raw": ""test" | 1 | true", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition without State > detects whether a prop is required 1`] = ` -{ - "bar": { - "description": "", - "required": false, - "tsType": { - "name": "number", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition without State > ignores hash map entry 1`] = ` -{ - "bar": { - "description": "", - "required": false, - "tsType": { - "name": "number", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition without State > special generic type annotations > unwraps $Exact<...> 1`] = `{}`; - -exports[`codeTypeHandler > TypeAlias (ts) > class definition without State > special generic type annotations > unwraps $ReadOnly<...> 1`] = `{}`; - -exports[`codeTypeHandler > TypeAlias (ts) > stateless TS component with Type > detects intersection types 1`] = ` -{ - "foo": { - "description": "", - "required": true, - "tsType": { - "elements": [ - { - "name": "Foo", - }, - { - "name": "Bar", - }, - ], - "name": "intersection", - "raw": "Foo & Bar", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > stateless TS component with Type > detects types correctly 1`] = ` -{ - "bar": { - "description": "", - "required": true, - "tsType": { - "name": "number", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, - "hal": { - "description": "", - "required": true, - "tsType": { - "name": "boolean", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > stateless TS component with Type > detects union types 1`] = ` -{ - "bar": { - "description": "", - "required": true, - "tsType": { - "elements": [ - { - "name": "literal", - "value": ""test"", - }, - { - "name": "literal", - "value": "1", - }, - { - "name": "literal", - "value": "true", - }, - ], - "name": "union", - "raw": ""test" | 1 | true", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > stateless TS component with Type > detects whether a prop is required 1`] = ` -{ - "bar": { - "description": "", - "required": false, - "tsType": { - "name": "number", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > stateless TS component with Type > ignores hash map entry 1`] = ` -{ - "bar": { - "description": "", - "required": false, - "tsType": { - "name": "number", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > stateless TS component with Type > special generic type annotations > unwraps $Exact<...> 1`] = `{}`; - -exports[`codeTypeHandler > TypeAlias (ts) > stateless TS component with Type > special generic type annotations > unwraps $ReadOnly<...> 1`] = `{}`; - -exports[`codeTypeHandler > TypeAlias (ts) > stateless component > detects intersection types 1`] = ` -{ - "foo": { - "description": "", - "required": true, - "tsType": { - "elements": [ - { - "name": "Foo", - }, - { - "name": "Bar", - }, - ], - "name": "intersection", - "raw": "Foo & Bar", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > stateless component > detects types correctly 1`] = ` -{ - "bar": { - "description": "", - "required": true, - "tsType": { - "name": "number", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, - "hal": { - "description": "", - "required": true, - "tsType": { - "name": "boolean", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > stateless component > detects union types 1`] = ` -{ - "bar": { - "description": "", - "required": true, - "tsType": { - "elements": [ - { - "name": "literal", - "value": ""test"", - }, - { - "name": "literal", - "value": "1", - }, - { - "name": "literal", - "value": "true", - }, - ], - "name": "union", - "raw": ""test" | 1 | true", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > stateless component > detects whether a prop is required 1`] = ` -{ - "bar": { - "description": "", - "required": false, - "tsType": { - "name": "number", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > stateless component > ignores hash map entry 1`] = ` -{ - "bar": { - "description": "", - "required": false, - "tsType": { - "name": "number", - }, - }, -} -`; - -exports[`codeTypeHandler > TypeAlias (ts) > stateless component > special generic type annotations > unwraps $Exact<...> 1`] = `{}`; - -exports[`codeTypeHandler > TypeAlias (ts) > stateless component > special generic type annotations > unwraps $ReadOnly<...> 1`] = `{}`; - -exports[`codeTypeHandler > does support utility types inline 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "name": "literal", - "value": "'fooValue'", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > forwardRef > resolves prop type from function expression 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > forwardRef > resolves when the function is not inline 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > forwardRef > resolves when the function is rebound and not inline 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > imported prop types > imported 1`] = ` -{ - "abc": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": false, - }, - "def": { - "description": "", - "flowType": { - "elements": [ - { - "name": "literal", - "value": ""test"", - }, - { - "name": "literal", - "value": "1", - }, - { - "name": "literal", - "value": "true", - }, - ], - "name": "union", - "raw": ""test" | 1 | true", - }, - "required": true, - }, - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, - "foobar": { - "description": "", - "flowType": { - "elements": [ - { - "name": "Foo", - }, - { - "name": "Bar", - }, - ], - "name": "intersection", - "raw": "Foo & Bar", - }, - "required": true, - }, - "hal": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > imported prop types > type imported 1`] = ` -{ - "abc": { - "description": "", - "flowType": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "string | number", - }, - "required": true, - }, - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": false, - }, - "def": { - "description": "", - "flowType": { - "elements": [ - { - "name": "literal", - "value": ""test"", - }, - { - "name": "literal", - "value": "1", - }, - { - "name": "literal", - "value": "true", - }, - ], - "name": "union", - "raw": ""test" | 1 | true", - }, - "required": true, - }, - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, - "foobar": { - "description": "", - "flowType": { - "elements": [ - { - "name": "Foo", - }, - { - "name": "Bar", - }, - ], - "name": "intersection", - "raw": "Foo & Bar", - }, - "required": true, - }, - "hal": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": true, - }, -} -`; - -exports[`codeTypeHandler > stateless TS component and variable type takes precedence 1`] = ` -{ - "foo": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, -} -`; - -exports[`codeTypeHandler > stateless TS component with 2 definitions 1`] = ` -{ - "additional": { - "description": "", - "required": true, - "tsType": { - "name": "boolean", - }, - }, - "bar": { - "description": "", - "required": true, - "tsType": { - "name": "number", - }, - }, -} -`; - -exports[`codeTypeHandler > supports intersection proptypes 1`] = ` -{ - "foo": { - "description": "", - "flowType": { - "name": "literal", - "value": "'bar'", - }, - "required": true, - }, -} -`; diff --git a/packages/react-docgen/src/handlers/__tests__/__snapshots__/componentMethodsHandler-test.ts.snap b/packages/react-docgen/src/handlers/__tests__/__snapshots__/componentMethodsHandler-test.ts.snap deleted file mode 100644 index 326ba010fcc..00000000000 --- a/packages/react-docgen/src/handlers/__tests__/__snapshots__/componentMethodsHandler-test.ts.snap +++ /dev/null @@ -1,310 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`componentMethodsHandler > function components > finds static methods on a component in a variable declaration 1`] = ` -[ - { - "docblock": null, - "modifiers": [ - "static", - ], - "name": "doFoo", - "params": [], - "returns": null, - }, - { - "docblock": null, - "modifiers": [ - "static", - ], - "name": "doBar", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > function components > finds static methods on a component in an assignment 1`] = ` -[ - { - "docblock": null, - "modifiers": [ - "static", - ], - "name": "doFoo", - "params": [], - "returns": null, - }, - { - "docblock": null, - "modifiers": [ - "static", - ], - "name": "doBar", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > function components > finds static methods on a function declaration 1`] = ` -[ - { - "docblock": null, - "modifiers": [ - "static", - ], - "name": "doFoo", - "params": [], - "returns": null, - }, - { - "docblock": null, - "modifiers": [ - "static", - ], - "name": "doBar", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > function components > resolves imported methods assigned on a component in an assignment 1`] = ` -[ - { - "docblock": null, - "modifiers": [ - "static", - ], - "name": "doFoo", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > function components > resolves imported methods assigned to static properties on a component 1`] = ` -[ - { - "docblock": null, - "modifiers": [ - "static", - ], - "name": "doFoo", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > function components > resolves imported methods on a function declaration 1`] = ` -[ - { - "docblock": null, - "modifiers": [ - "static", - ], - "name": "doFoo", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > resolves imported methods assigned to computed properties 1`] = ` -[ - { - "docblock": "The foo method", - "modifiers": [], - "name": "@computed#foo", - "params": [ - { - "name": "bar", - "optional": false, - "type": { - "name": "number", - }, - }, - ], - "returns": { - "type": { - "name": "number", - }, - }, - }, -] -`; - -exports[`componentMethodsHandler > should handle and ignore computed methods 1`] = ` -[ - { - "docblock": "The foo method", - "modifiers": [], - "name": "@computed#foo", - "params": [ - { - "name": "bar", - "optional": false, - "type": { - "name": "number", - }, - }, - ], - "returns": { - "type": { - "name": "number", - }, - }, - }, -] -`; - -exports[`componentMethodsHandler > useImperativeHandle > AssignmentExpression and useImperativeHandle 1`] = ` -[ - { - "docblock": null, - "modifiers": [ - "static", - ], - "name": "other", - "params": [], - "returns": null, - }, - { - "docblock": null, - "modifiers": [], - "name": "method", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > useImperativeHandle > VariableDeclaration and useImperativeHandle 1`] = ` -[ - { - "docblock": null, - "modifiers": [ - "static", - ], - "name": "other", - "params": [], - "returns": null, - }, - { - "docblock": null, - "modifiers": [], - "name": "method", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > useImperativeHandle > assigned ReturnStatement > ArrowFunctionExpression Component 1`] = ` -[ - { - "docblock": null, - "modifiers": [], - "name": "method", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > useImperativeHandle > assigned ReturnStatement > FunctionDeclaration Component 1`] = ` -[ - { - "docblock": null, - "modifiers": [], - "name": "method", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > useImperativeHandle > assigned ReturnStatement > FunctionExpression Component 1`] = ` -[ - { - "docblock": null, - "modifiers": [], - "name": "method", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > useImperativeHandle > direct ObjectExpression > ArrowFunctionExpression Component 1`] = ` -[ - { - "docblock": null, - "modifiers": [], - "name": "method", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > useImperativeHandle > direct ObjectExpression > FunctionDeclaration Component 1`] = ` -[ - { - "docblock": null, - "modifiers": [], - "name": "method", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > useImperativeHandle > direct ObjectExpression > FunctionExpression Component 1`] = ` -[ - { - "docblock": null, - "modifiers": [], - "name": "method", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > useImperativeHandle > regular ReturnStatement > ArrowFunctionExpression Component 1`] = ` -[ - { - "docblock": null, - "modifiers": [], - "name": "method", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > useImperativeHandle > regular ReturnStatement > FunctionDeclaration Component 1`] = ` -[ - { - "docblock": null, - "modifiers": [], - "name": "method", - "params": [], - "returns": null, - }, -] -`; - -exports[`componentMethodsHandler > useImperativeHandle > regular ReturnStatement > FunctionExpression Component 1`] = ` -[ - { - "docblock": null, - "modifiers": [], - "name": "method", - "params": [], - "returns": null, - }, -] -`; diff --git a/packages/react-docgen/src/handlers/__tests__/__snapshots__/componentMethodsJsDocHandler-test.ts.snap b/packages/react-docgen/src/handlers/__tests__/__snapshots__/componentMethodsJsDocHandler-test.ts.snap deleted file mode 100644 index 15f5b944bf3..00000000000 --- a/packages/react-docgen/src/handlers/__tests__/__snapshots__/componentMethodsJsDocHandler-test.ts.snap +++ /dev/null @@ -1,82 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`componentMethodsJsDocHandler > adds descriptions 1`] = ` -[ - { - "description": "The foo method.", - "docblock": " - The foo method. - @param test The test - @returns The number - ", - "modifiers": [], - "name": "foo", - "params": [ - { - "description": "The test", - "name": "test", - "optional": false, - }, - ], - "returns": { - "description": "The number", - }, - }, -] -`; - -exports[`componentMethodsJsDocHandler > adds js doc types when no flow types 1`] = ` -[ - { - "description": null, - "docblock": " - @param {string} test - @returns {string} - ", - "modifiers": [], - "name": "foo", - "params": [ - { - "name": "test", - "optional": false, - "type": { - "name": "string", - }, - }, - ], - "returns": { - "type": { - "name": "string", - }, - }, - }, -] -`; - -exports[`componentMethodsJsDocHandler > keeps flow types over js doc types 1`] = ` -[ - { - "description": null, - "docblock": " - @param {string} test - @returns {string} - ", - "modifiers": [], - "name": "foo", - "params": [ - { - "name": "test", - "optional": false, - "type": { - "name": "number", - }, - }, - ], - "returns": { - "type": { - "name": "number", - }, - }, - }, -] -`; diff --git a/packages/react-docgen/src/handlers/__tests__/__snapshots__/defaultPropsHandler-test.ts.snap b/packages/react-docgen/src/handlers/__tests__/__snapshots__/defaultPropsHandler-test.ts.snap deleted file mode 100644 index ad125e9f086..00000000000 --- a/packages/react-docgen/src/handlers/__tests__/__snapshots__/defaultPropsHandler-test.ts.snap +++ /dev/null @@ -1,669 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`defaultPropsHandler > ClassDeclaration with static defaultProps > can resolve default props that are imported given a custom importer 1`] = ` -{ - "baz": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, -} -`; - -exports[`defaultPropsHandler > ClassDeclaration with static defaultProps > resolves imported spreads 1`] = ` -{ - "bar": { - "defaultValue": { - "computed": false, - "value": ""foo"", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > ClassDeclaration with static defaultProps > resolves imported values assigned as default props 1`] = ` -{ - "abc": { - "defaultValue": { - "computed": false, - "value": "{xyz: abc.def, 123: 42}", - }, - }, - "bar": { - "defaultValue": { - "computed": false, - "value": "42", - }, - }, - "baz": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > ClassDeclaration with static defaultProps > should find prop default values that are imported variables 1`] = ` -{ - "foo": { - "defaultValue": { - "computed": true, - "value": "ImportedComponent", - }, - }, -} -`; - -exports[`defaultPropsHandler > ClassDeclaration with static defaultProps > should find prop default values that are literals 1`] = ` -{ - "abc": { - "defaultValue": { - "computed": false, - "value": "{xyz: abc.def, 123: 42}", - }, - }, - "bar": { - "defaultValue": { - "computed": false, - "value": "42", - }, - }, - "baz": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > ClassDeclaration with static defaultProps > should find prop default values that are literals 2`] = ` -{ - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > ClassDeclaration with static defaultProps > should resolve local spreads 1`] = ` -{ - "bar": { - "defaultValue": { - "computed": false, - "value": ""foo"", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > ClassExpression with static defaultProps > resolves imported values assigned as default props 1`] = ` -{ - "abc": { - "defaultValue": { - "computed": false, - "value": "{xyz: abc.def, 123: 42}", - }, - }, - "bar": { - "defaultValue": { - "computed": false, - "value": "42", - }, - }, - "baz": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > ClassExpression with static defaultProps > should find prop default values that are literals 1`] = ` -{ - "abc": { - "defaultValue": { - "computed": false, - "value": "{xyz: abc.def, 123: 42}", - }, - }, - "bar": { - "defaultValue": { - "computed": false, - "value": "42", - }, - }, - "baz": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > Functional components with default params > allows imported defaults to be aliased 1`] = ` -{ - "foo": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, -} -`; - -exports[`defaultPropsHandler > Functional components with default params > can use imported values as default props 1`] = ` -{ - "bar": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, -} -`; - -exports[`defaultPropsHandler > Functional components with default params > overrides with imported defaultProps 1`] = ` -{ - "bar": { - "defaultValue": { - "computed": false, - "value": ""foo"", - }, - }, -} -`; - -exports[`defaultPropsHandler > Functional components with default params > resolves imported spreads 1`] = ` -{ - "bar": { - "defaultValue": { - "computed": false, - "value": ""foo"", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > Functional components with default params > resolves local spreads 1`] = ` -{ - "bar": { - "defaultValue": { - "computed": false, - "value": ""foo"", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > Functional components with default params > should find default props that are literals 1`] = ` -{ - "abc": { - "defaultValue": { - "computed": false, - "value": "{xyz: abc.def, 123: 42}", - }, - }, - "bar": { - "defaultValue": { - "computed": false, - "value": "42", - }, - }, - "baz": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > Functional components with default params > should find prop default values that are imported variables 1`] = ` -{ - "foo": { - "defaultValue": { - "computed": true, - "value": "ImportedComponent", - }, - }, -} -`; - -exports[`defaultPropsHandler > Functional components with default params > should override with defaultProps if available 1`] = ` -{ - "abc": { - "defaultValue": { - "computed": false, - "value": "{xyz: abc.def, 123: 42}", - }, - }, - "bar": { - "defaultValue": { - "computed": false, - "value": "42", - }, - }, - "baz": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > Functional components with default params > should work with aliases 1`] = ` -{ - "abc": { - "defaultValue": { - "computed": false, - "value": "{xyz: abc.def, 123: 42}", - }, - }, - "bar": { - "defaultValue": { - "computed": false, - "value": "42", - }, - }, - "baz": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > Functional components with default params > should work with no defaults 1`] = `{}`; - -exports[`defaultPropsHandler > ObjectExpression > can resolve declared functions 1`] = ` -{ - "abc": { - "defaultValue": { - "computed": false, - "value": "{xyz: abc.def, 123: 42}", - }, - }, - "bar": { - "defaultValue": { - "computed": false, - "value": "42", - }, - }, - "baz": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > ObjectExpression > can resolve object methods 1`] = ` -{ - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > ObjectExpression > handles computed properties 1`] = ` -{ - "@computed#bar": { - "defaultValue": { - "computed": false, - "value": "42", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > ObjectExpression > handles imported values assigned to computed properties 1`] = ` -{ - "@computed#bar": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > ObjectExpression > ignores complex computed properties 1`] = ` -{ - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > ObjectExpression > ignores imported values assigned to complex computed properties 1`] = ` -{ - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > ObjectExpression > resolves imported spreads 1`] = ` -{ - "bar": { - "defaultValue": { - "computed": false, - "value": ""foo"", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > ObjectExpression > resolves local spreads 1`] = ` -{ - "bar": { - "defaultValue": { - "computed": false, - "value": ""foo"", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > ObjectExpression > should find prop default values that are literals 1`] = ` -{ - "abc": { - "defaultValue": { - "computed": false, - "value": "{xyz: abc.def, 123: 42}", - }, - }, - "bar": { - "defaultValue": { - "computed": false, - "value": "42", - }, - }, - "baz": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, - "bigint": { - "defaultValue": { - "computed": false, - "value": "1n", - }, - }, - "falseliteral": { - "defaultValue": { - "computed": false, - "value": "false", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, - "nullliteral": { - "defaultValue": { - "computed": false, - "value": "null", - }, - }, - "regex": { - "defaultValue": { - "computed": false, - "value": "/./", - }, - }, - "trueliteral": { - "defaultValue": { - "computed": false, - "value": "true", - }, - }, -} -`; - -exports[`defaultPropsHandler > ObjectExpression > should find prop default values that are literals from imported functions 1`] = ` -{ - "abc": { - "defaultValue": { - "computed": false, - "value": "{xyz: abc.def, 123: 42}", - }, - }, - "bar": { - "defaultValue": { - "computed": false, - "value": "42", - }, - }, - "baz": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, - "foo": { - "defaultValue": { - "computed": false, - "value": ""bar"", - }, - }, -} -`; - -exports[`defaultPropsHandler > can have an importer that resolves spread properties 1`] = ` -{ - "123": { - "defaultValue": { - "computed": false, - "value": "42", - }, - }, - "bar": { - "defaultValue": { - "computed": false, - "value": "42", - }, - }, - "xyz": { - "defaultValue": { - "computed": true, - "value": "abc.def", - }, - }, -} -`; - -exports[`defaultPropsHandler > forwardRef > also resolves imports when the function is not inline 1`] = ` -{ - "bar": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, -} -`; - -exports[`defaultPropsHandler > forwardRef > resolves default props in the parameters 1`] = ` -{ - "foo": { - "defaultValue": { - "computed": false, - "value": "'bar'", - }, - }, -} -`; - -exports[`defaultPropsHandler > forwardRef > resolves defaultProps 1`] = ` -{ - "foo": { - "defaultValue": { - "computed": false, - "value": "'baz'", - }, - }, -} -`; - -exports[`defaultPropsHandler > forwardRef > resolves imported default props in the parameters 1`] = ` -{ - "bar": { - "defaultValue": { - "computed": false, - "value": "["foo", "bar"]", - }, - }, -} -`; - -exports[`defaultPropsHandler > forwardRef > resolves imported defaultProps 1`] = ` -{ - "bar": { - "defaultValue": { - "computed": false, - "value": ""foo"", - }, - }, -} -`; - -exports[`defaultPropsHandler > forwardRef > resolves when the function is not inline 1`] = ` -{ - "foo": { - "defaultValue": { - "computed": false, - "value": "'bar'", - }, - }, -} -`; - -exports[`defaultPropsHandler > should only consider Property nodes, not e.g. spread properties 1`] = ` -{ - "bar": { - "defaultValue": { - "computed": false, - "value": "42", - }, - }, -} -`; diff --git a/packages/react-docgen/src/handlers/__tests__/__snapshots__/propTypeHandler-test.ts.snap b/packages/react-docgen/src/handlers/__tests__/__snapshots__/propTypeHandler-test.ts.snap deleted file mode 100644 index 8dbbfe3d37d..00000000000 --- a/packages/react-docgen/src/handlers/__tests__/__snapshots__/propTypeHandler-test.ts.snap +++ /dev/null @@ -1,309 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`propTypeHandler > React.createClass > can resolve individual imported variables assigned to props 1`] = ` -{ - "@computed#bar": { - "required": false, - "type": {}, - }, - "baz": { - "required": false, - "type": {}, - }, - "complex_prop": { - "required": true, - "type": {}, - }, - "foo": { - "required": false, - "type": {}, - }, - "simple_prop": { - "required": true, - "type": {}, - }, -} -`; - -exports[`propTypeHandler > React.createClass > handles computed properties 1`] = ` -{ - "@computed#foo": { - "required": true, - "type": {}, - }, - "complex_prop": { - "required": true, - "type": {}, - }, -} -`; - -exports[`propTypeHandler > React.createClass > ignores complex computed properties 1`] = ` -{ - "complex_prop": { - "required": true, - "type": {}, - }, -} -`; - -exports[`propTypeHandler > React.createClass > passes the correct argument to getPropType 1`] = ` -Node { - "computed": false, - "object": Node { - "name": "PropTypes", - "type": "Identifier", - }, - "property": Node { - "name": "bool", - "type": "Identifier", - }, - "type": "MemberExpression", -} -`; - -exports[`propTypeHandler > React.createClass > passes the correct argument to getPropType 2`] = ` -Node { - "computed": false, - "object": Node { - "name": "PropTypes", - "type": "Identifier", - }, - "property": Node { - "name": "xyz", - "type": "Identifier", - }, - "type": "MemberExpression", -} -`; - -exports[`propTypeHandler > class definition > class property > can resolve individual imported variables assigned to props 1`] = ` -{ - "@computed#bar": { - "required": false, - "type": {}, - }, - "baz": { - "required": false, - "type": {}, - }, - "complex_prop": { - "required": true, - "type": {}, - }, - "foo": { - "required": false, - "type": {}, - }, - "simple_prop": { - "required": true, - "type": {}, - }, -} -`; - -exports[`propTypeHandler > class definition > class property > handles computed properties 1`] = ` -{ - "@computed#foo": { - "required": true, - "type": {}, - }, - "complex_prop": { - "required": true, - "type": {}, - }, -} -`; - -exports[`propTypeHandler > class definition > class property > ignores complex computed properties 1`] = ` -{ - "complex_prop": { - "required": true, - "type": {}, - }, -} -`; - -exports[`propTypeHandler > class definition > class property > passes the correct argument to getPropType 1`] = ` -Node { - "computed": false, - "object": Node { - "name": "PropTypes", - "type": "Identifier", - }, - "property": Node { - "name": "bool", - "type": "Identifier", - }, - "type": "MemberExpression", -} -`; - -exports[`propTypeHandler > class definition > class property > passes the correct argument to getPropType 2`] = ` -Node { - "computed": false, - "object": Node { - "name": "PropTypes", - "type": "Identifier", - }, - "property": Node { - "name": "xyz", - "type": "Identifier", - }, - "type": "MemberExpression", -} -`; - -exports[`propTypeHandler > class definition > static getter > can resolve individual imported variables assigned to props 1`] = ` -{ - "@computed#bar": { - "required": false, - "type": {}, - }, - "baz": { - "required": false, - "type": {}, - }, - "complex_prop": { - "required": true, - "type": {}, - }, - "foo": { - "required": false, - "type": {}, - }, - "simple_prop": { - "required": true, - "type": {}, - }, -} -`; - -exports[`propTypeHandler > class definition > static getter > handles computed properties 1`] = ` -{ - "@computed#foo": { - "required": true, - "type": {}, - }, - "complex_prop": { - "required": true, - "type": {}, - }, -} -`; - -exports[`propTypeHandler > class definition > static getter > ignores complex computed properties 1`] = ` -{ - "complex_prop": { - "required": true, - "type": {}, - }, -} -`; - -exports[`propTypeHandler > class definition > static getter > passes the correct argument to getPropType 1`] = ` -Node { - "computed": false, - "object": Node { - "name": "PropTypes", - "type": "Identifier", - }, - "property": Node { - "name": "bool", - "type": "Identifier", - }, - "type": "MemberExpression", -} -`; - -exports[`propTypeHandler > class definition > static getter > passes the correct argument to getPropType 2`] = ` -Node { - "computed": false, - "object": Node { - "name": "PropTypes", - "type": "Identifier", - }, - "property": Node { - "name": "xyz", - "type": "Identifier", - }, - "type": "MemberExpression", -} -`; - -exports[`propTypeHandler > stateless component > can resolve individual imported variables assigned to props 1`] = ` -{ - "@computed#bar": { - "required": false, - "type": {}, - }, - "baz": { - "required": false, - "type": {}, - }, - "complex_prop": { - "required": true, - "type": {}, - }, - "foo": { - "required": false, - "type": {}, - }, - "simple_prop": { - "required": true, - "type": {}, - }, -} -`; - -exports[`propTypeHandler > stateless component > handles computed properties 1`] = ` -{ - "@computed#foo": { - "required": true, - "type": {}, - }, - "complex_prop": { - "required": true, - "type": {}, - }, -} -`; - -exports[`propTypeHandler > stateless component > ignores complex computed properties 1`] = ` -{ - "complex_prop": { - "required": true, - "type": {}, - }, -} -`; - -exports[`propTypeHandler > stateless component > passes the correct argument to getPropType 1`] = ` -Node { - "computed": false, - "object": Node { - "name": "PropTypes", - "type": "Identifier", - }, - "property": Node { - "name": "bool", - "type": "Identifier", - }, - "type": "MemberExpression", -} -`; - -exports[`propTypeHandler > stateless component > passes the correct argument to getPropType 2`] = ` -Node { - "computed": false, - "object": Node { - "name": "PropTypes", - "type": "Identifier", - }, - "property": Node { - "name": "xyz", - "type": "Identifier", - }, - "type": "MemberExpression", -} -`; diff --git a/packages/react-docgen/src/handlers/__tests__/codeTypeHandler-test.ts b/packages/react-docgen/src/handlers/__tests__/codeTypeHandler-test.ts deleted file mode 100644 index 633350c9530..00000000000 --- a/packages/react-docgen/src/handlers/__tests__/codeTypeHandler-test.ts +++ /dev/null @@ -1,446 +0,0 @@ -import { parse, makeMockImporter, parseTypescript } from '../../../tests/utils'; -import DocumentationBuilder from '../../Documentation'; -import codeTypeHandler from '../codeTypeHandler.js'; -import type DocumentationMock from '../../__mocks__/Documentation'; -import type { - VariableDeclaration, - ArrowFunctionExpression, - CallExpression, - ClassDeclaration, - ExportNamedDeclaration, - ObjectExpression, -} from '@babel/types'; -import type { NodePath } from '@babel/traverse'; -import type { ComponentNode } from '../../resolver'; -import { beforeEach, describe, expect, test, vi } from 'vitest'; - -vi.mock('../../Documentation.js'); - -describe('codeTypeHandler', () => { - let documentation: DocumentationBuilder & DocumentationMock; - - beforeEach(() => { - documentation = new DocumentationBuilder() as DocumentationBuilder & - DocumentationMock; - }); - - const mockImporter = makeMockImporter({ - something: (stmtLast) => - stmtLast(` - export type Props = { - foo: string, - bar?: number, - hal: boolean, - [key: string]: string, - abc: string | number, - def: "test" | 1 | true, - foobar: Foo & Bar, - }; - `).get('declaration') as NodePath, - }); - - function template(src: string, typeObject: string): string { - return ` - ${src} - var React = require('React'); - var Component = React.Component; - - type Props = ${typeObject}; - `; - } - - function testCodeTypeHandler( - getSrc: (src: string) => NodePath, - ) { - test('detects types correctly', () => { - const flowTypesSrc = ` - { - foo: string, - bar: number, - hal: boolean, - } - `; - const definition = getSrc(flowTypesSrc); - - codeTypeHandler(documentation, definition); - - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('detects whether a prop is required', () => { - const flowTypesSrc = ` - { - foo: string, - bar?: number, - } - `; - const definition = getSrc(flowTypesSrc); - - codeTypeHandler(documentation, definition); - - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('ignores hash map entry', () => { - const flowTypesSrc = ` - { - [key: string]: string, - bar?: number, - } - `; - const definition = getSrc(flowTypesSrc); - - codeTypeHandler(documentation, definition); - - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('detects union types', () => { - const flowTypesSrc = ` - { - foo: string | number, - bar: "test" | 1 | true, - } - `; - const definition = getSrc(flowTypesSrc); - - codeTypeHandler(documentation, definition); - - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('detects intersection types', () => { - const flowTypesSrc = ` - { - foo: Foo & Bar, - } - `; - const definition = getSrc(flowTypesSrc); - - codeTypeHandler(documentation, definition); - - expect(documentation.descriptors).toMatchSnapshot(); - }); - - describe('special generic type annotations', () => { - ['$ReadOnly', '$Exact'].forEach((annotation) => { - test(`unwraps ${annotation}<...>`, () => { - const flowTypesSrc = ` - ${annotation}<{ - foo: string | number, - }> - `; - - const definition = getSrc(flowTypesSrc); - - codeTypeHandler(documentation, definition); - - expect(documentation.descriptors).toMatchSnapshot(); - }); - }); - }); - } - - describe.each([ - ['flow', parse], - ['ts', parseTypescript], - ])('TypeAlias (%s)', (name, parseFunc) => { - describe.runIf(name === 'flow')('class definition for flow <0.53', () => { - testCodeTypeHandler((propTypesSrc) => - parseFunc.statement( - template( - 'class Foo extends Component {}', - propTypesSrc, - ), - ), - ); - }); - - describe('class definition without State', () => { - testCodeTypeHandler((propTypesSrc) => - parseFunc.statement( - template('class Foo extends Component {}', propTypesSrc), - ), - ); - }); - - describe('class definition with State', () => { - testCodeTypeHandler((propTypesSrc) => - parseFunc.statement( - template( - 'class Foo extends Component {}', - propTypesSrc, - ), - ), - ); - }); - - describe('class definition with inline props', () => { - testCodeTypeHandler((propTypesSrc) => - parseFunc.statement( - template( - 'class Foo extends Component { props: Props; }', - propTypesSrc, - ), - ), - ); - }); - - describe('stateless component', () => { - testCodeTypeHandler( - (propTypesSrc) => - parseFunc - .statement(template('(props: Props) => null;', propTypesSrc)) - .get('expression') as NodePath, - ); - }); - - describe.runIf(name === 'ts')('stateless TS component with Type', () => { - testCodeTypeHandler( - (propTypesSrc) => - parseFunc - .statement( - template( - 'const MyComponent:React.FC = (props) => null;', - propTypesSrc, - ), - ) - .get('declarations')[0] - .get('init') as NodePath, - ); - }); - }); - - describe('does not error if flowTypes cannot be found', () => { - test('ObjectExpression', () => { - const definition = parse.expression('{fooBar: 42}'); - - expect(() => codeTypeHandler(documentation, definition)).not.toThrow(); - }); - - test('ClassDeclaration', () => { - const definition = parse.statement( - 'class Foo extends Component {}', - ); - - expect(() => codeTypeHandler(documentation, definition)).not.toThrow(); - }); - - test('ArrowFunctionExpression', () => { - const definition = - parse.statement('() =>
'); - - expect(() => codeTypeHandler(documentation, definition)).not.toThrow(); - }); - }); - - test('supports intersection proptypes', () => { - const definition = parse - .statement( - `(props: Props) =>
; - var React = require('React'); - import type Imported from 'something'; - type Props = Imported & { foo: 'bar' };`, - ) - .get('expression') as NodePath; - - codeTypeHandler(documentation, definition); - - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('does support utility types inline', () => { - const definition = parse - .statement( - `(props: $ReadOnly) =>
; - var React = require('React'); - type Props = { foo: 'fooValue' };`, - ) - .get('expression') as NodePath; - - expect(() => codeTypeHandler(documentation, definition)).not.toThrow(); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('does not support union proptypes', () => { - const definition = parse - .statement( - `(props: Props) =>
; - var React = require('React'); - import type Imported from 'something'; - type Other = { bar: 'barValue' }; - type Props = Imported | Other | { foo: 'fooValue' };`, - ) - .get('expression') as NodePath; - - expect(() => codeTypeHandler(documentation, definition)).not.toThrow(); - expect(documentation.descriptors).toEqual({}); - }); - - describe('imported prop types', () => { - test('does not resolve type included by require', () => { - const definition = parse - .statement( - `(props: Props) =>
; - var React = require('React'); - var Component = React.Component; - var Props = require('something');`, - mockImporter, - ) - .get('expression') as NodePath; - - expect(() => codeTypeHandler(documentation, definition)).not.toThrow(); - expect(documentation.descriptors).toEqual({}); - }); - - test('imported', () => { - const definition = parse - .statement( - `(props: Props) =>
; - var React = require('React'); - var Component = React.Component; - import { Props } from 'something';`, - mockImporter, - ) - .get('expression') as NodePath; - - expect(() => codeTypeHandler(documentation, definition)).not.toThrow(); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('type not imported', () => { - const definition = parse - .statement( - `(props: Props) =>
; - var React = require('React'); - var Component = React.Component; - import type { Props } from 'something';`, - ) - .get('expression') as NodePath; - - expect(() => codeTypeHandler(documentation, definition)).not.toThrow(); - expect(documentation.descriptors).toEqual({}); - }); - - test('type imported', () => { - const definition = parse - .statement( - `(props: Props) =>
; - var React = require('React'); - var Component = React.Component; - import type { Props } from 'something';`, - mockImporter, - ) - .get('expression') as NodePath; - - expect(() => codeTypeHandler(documentation, definition)).not.toThrow(); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('does not resolve types not in scope', () => { - const definition = parse - .statement( - `(props: Props) =>
; - var React = require('React'); - var Component = React.Component;`, - mockImporter, - ) - .get('expression') as NodePath; - - expect(() => codeTypeHandler(documentation, definition)).not.toThrow(); - expect(documentation.descriptors).toEqual({}); - }); - - test('does not resolve types not in scope', () => { - const definition = parse - .statement( - `(props: Props) =>
; - var React = require('React'); - var Component = React.Component;`, - mockImporter, - ) - .get('expression') as NodePath; - - expect(() => codeTypeHandler(documentation, definition)).not.toThrow(); - expect(documentation.descriptors).toEqual({}); - }); - }); - - describe('forwardRef', () => { - test('resolves prop type from function expression', () => { - const src = ` - import React from 'react'; - type Props = { foo: string }; - React.forwardRef((props: Props, ref) =>
{props.foo}
); - `; - - codeTypeHandler(documentation, parse.expressionLast(src)); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('resolves when the function is not inline', () => { - const src = ` - import React from 'react'; - type Props = { foo: string }; - const ComponentImpl = (props: Props, ref) =>
{props.foo}
; - React.forwardRef(ComponentImpl); - `; - - codeTypeHandler(documentation, parse.expressionLast(src)); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('resolves when the function is rebound and not inline', () => { - const src = ` - import React from 'react'; - type Props = { foo: string }; - let Component = (props: Props, ref) =>
{props.foo}
; - Component = React.forwardRef(Component); - `; - - codeTypeHandler( - documentation, - parse.expressionLast(src).get('right') as NodePath, - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - }); - - test('stateless TS component with 2 definitions', () => { - const definition = parseTypescript - .statement( - ` - const MyComponent: React.FC<{ additional: boolean }> = (props: Props) => null; - var React = require('React'); - var Component = React.Component; - - type Props = { bar: number }; - `, - ) - .get('declarations')[0] - .get('init') as NodePath; - - codeTypeHandler(documentation, definition); - - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('stateless TS component and variable type takes precedence', () => { - const definition = parseTypescript - .statement( - ` - const MyComponent: React.FC<{ foo: string }> = (props: Props) => null; - var React = require('React'); - var Component = React.Component; - - type Props = { foo: number }; - `, - ) - .get('declarations')[0] - .get('init') as NodePath; - - codeTypeHandler(documentation, definition); - - expect(documentation.descriptors).toMatchSnapshot(); - }); -}); diff --git a/packages/react-docgen/src/handlers/__tests__/componentDocblockHandler-test.ts b/packages/react-docgen/src/handlers/__tests__/componentDocblockHandler-test.ts deleted file mode 100644 index 4683bb64dac..00000000000 --- a/packages/react-docgen/src/handlers/__tests__/componentDocblockHandler-test.ts +++ /dev/null @@ -1,455 +0,0 @@ -import { makeMockImporter, parse } from '../../../tests/utils'; -import componentDocblockHandler from '../componentDocblockHandler.js'; -import DocumentationBuilder from '../../Documentation'; -import type DocumentationMock from '../../__mocks__/Documentation'; -import type { NodePath } from '@babel/traverse'; -import type { - ArrowFunctionExpression, - CallExpression, - ClassDeclaration, - ClassExpression, - ExportDefaultDeclaration, - FunctionDeclaration, - FunctionExpression, - ObjectExpression, - VariableDeclaration, -} from '@babel/types'; -import type { ComponentNode } from '../../resolver'; -import { beforeEach, describe, expect, test, vi } from 'vitest'; - -vi.mock('../../Documentation.js'); - -describe('componentDocblockHandler', () => { - let documentation: DocumentationBuilder & DocumentationMock; - - beforeEach(() => { - documentation = new DocumentationBuilder() as DocumentationBuilder & - DocumentationMock; - }); - - function testDockblockHandler( - definitionSrc: string, - parseFunc: (src: string) => NodePath, - ) { - test('finds docblocks for component definitions', () => { - const definition = parseFunc(` - import something from 'somewhere'; - - /** - * Component description - */ - ${definitionSrc} - `); - - componentDocblockHandler(documentation, definition); - expect(documentation.description).toBe('Component description'); - }); - - test('ignores other types of comments', () => { - let definition = parseFunc(` - import something from 'somewhere'; - - /* - * This is not a docblock', - */ - ${definitionSrc} - `); - - componentDocblockHandler(documentation, definition); - expect(documentation.description).toBe(''); - - definition = parseFunc(` - // Inline comment' - ${definitionSrc} - `); - - componentDocblockHandler(documentation, definition); - expect(documentation.description).toBe(''); - }); - - test('only considers the docblock directly above the definition', () => { - const definition = parseFunc(` - import something from 'somewhere'; - - /** - * This is the wrong docblock - */ - var something_else = "foo"; - ${definitionSrc} - `); - - componentDocblockHandler(documentation, definition); - expect(documentation.description).toBe(''); - }); - } - - /** - * Decorates can only be assigned to class and therefore only make sense for - * class declarations and export declarations. - */ - function testDecorators( - classSrc: string, - parseFunc: (src: string) => NodePath, - exportSrc = '', - ) { - describe('decorators', () => { - test("uses the docblock above the decorator if it's the only one", () => { - const definition = parseFunc(` - import something from 'somewhere'; - /** - * Component description - */ - ${exportSrc} - @Decorator1 - @Decorator2 - ${classSrc} - `); - - componentDocblockHandler(documentation, definition); - expect(documentation.description).toBe('Component description'); - }); - - test('uses the component docblock if present', () => { - const definition = parseFunc(` - import something from 'somewhere'; - - ${exportSrc} - /** - * Decorator description - */ - @Decorator1 - @Decorator2 - /** - * Component description - */ - ${classSrc} - `); - - componentDocblockHandler(documentation, definition); - expect(documentation.description).toBe('Component description'); - }); - }); - } - - function testImports( - exportSrc: string, - importName: string, - useDefault = false, - ) { - const importDef = useDefault ? `${importName}` : `{ ${importName} }`; - - const mockImporter = makeMockImporter({ - test1: (stmtLast) => - stmtLast( - ` - /** - * Component description - */ - ${exportSrc} - `, - false, - 0, - ).get('declaration') as NodePath, - - test2: (stmtLast) => - stmtLast(` - import ${importDef} from 'test1'; - export default ${importName}; - `).get('declaration'), - }); - - describe('imports', () => { - test('can use a custom importer to resolve docblocks on imported components', () => { - const program = parse - .statementLast( - `import ${importDef} from 'test1'; - export default ${importName};`, - mockImporter, - ) - .get('declaration') as NodePath; - - componentDocblockHandler(documentation, program); - expect(documentation.description).toBe('Component description'); - }); - }); - - test('traverses multiple imports', () => { - const program = parse - .statementLast( - `import ${importDef} from 'test2'; - export default ${importName};`, - mockImporter, - ) - .get('declaration') as NodePath; - - componentDocblockHandler(documentation, program); - expect(documentation.description).toBe('Component description'); - }); - } - - describe('React.createClass', () => { - testDockblockHandler( - 'var Component = React.createClass({})', - (src) => - parse - .statementLast(src) - .get('declarations.0.init.arguments.0') as NodePath, - ); - testImports('export var Component = React.createClass({})', 'Component'); - }); - - describe('ClassDeclaration', () => { - testDockblockHandler('class Component {}', (src) => - parse.statementLast(src), - ); - testDecorators('class Component {}', (src) => parse.statementLast(src)); - testImports('export class Component {}', 'Component'); - }); - - describe('ClassExpression', () => { - testDockblockHandler( - 'var Component = class {};', - (src) => - parse - .statementLast(src) - .get('declarations.0.init') as NodePath, - ); - testImports('export var Component = class {};', 'Component'); - }); - - describe('Stateless functions', () => { - testDockblockHandler('function Component() {}', (src) => - parse.statementLast(src), - ); - testImports('export function Component() {}', 'Component'); - testDockblockHandler( - 'var Component = function () {};', - (src) => - parse - .statementLast(src) - .get('declarations.0.init') as NodePath, - ); - testImports('export var Component = function () {};', 'Component'); - testDockblockHandler( - 'var Component = () => {}', - (src) => - parse - .statementLast(src) - .get('declarations.0.init') as NodePath, - ); - testImports('export var Component = () => {}', 'Component'); - }); - - describe('ESM default export', () => { - describe('Default React.createClass export', () => { - testDockblockHandler( - 'export default React.createClass({});', - (src) => - parse - .statementLast(src) - .get('declaration.arguments.0') as NodePath, - ); - }); - - describe('Default class declaration export', () => { - testDockblockHandler( - 'export default class Component {}', - (src) => - parse - .statementLast(src) - .get('declaration') as NodePath, - ); - testDecorators( - 'class Component {}', - (src) => - parse - .statementLast(src) - .get('declaration') as NodePath, - 'export default', - ); - }); - - describe('Default class expression export', () => { - testDockblockHandler( - 'export default class {}', - (src) => - parse - .statementLast(src) - .get('declaration') as NodePath, - ); - testDecorators( - 'class {}', - (src) => - parse - .statementLast(src) - .get('declaration') as NodePath, - 'export default', - ); - }); - - describe('Default stateless function export', () => { - describe('named function', () => { - testDockblockHandler( - 'export default function Component() {}', - (src) => - parse - .statementLast(src) - .get('declaration') as NodePath, - ); - }); - - describe('anonymous function', () => { - testDockblockHandler( - 'export default function() {}', - (src) => - parse - .statementLast(src) - .get('declaration') as NodePath, - ); - }); - - describe('arrow function', () => { - testDockblockHandler( - 'export default () => {}', - (src) => - parse - .statementLast(src) - .get('declaration') as NodePath, - ); - }); - }); - }); - - describe('ESM named export', () => { - describe('Named React.createClass export', () => { - testDockblockHandler( - 'export var Component = React.createClass({});', - (src) => - parse - .statementLast(src) - .get( - 'declaration.declarations.0.init.arguments.0', - ) as NodePath, - ); - }); - - describe('Named class declaration export', () => { - testDockblockHandler( - 'export class Component {}', - (src) => - parse - .statementLast(src) - .get('declaration') as NodePath, - ); - testDecorators( - 'class Component {}', - (src) => - parse - .statementLast(src) - .get('declaration') as NodePath, - 'export', - ); - }); - - describe('Named stateless function', () => { - describe('named function', () => { - testDockblockHandler( - 'export function Component() {}', - (src) => - parse - .statementLast(src) - .get('declaration') as NodePath, - ); - }); - - describe('anonymous function', () => { - testDockblockHandler( - 'export var Component = function() {}', - (src) => - parse - .statementLast(src) - .get('declaration') as NodePath, - ); - }); - - describe('arrow function', () => { - testDockblockHandler( - 'export var Component = () => {}', - (src) => - parse - .statementLast(src) - .get('declaration') as NodePath, - ); - }); - }); - }); - - describe('forwardRef', () => { - const useDefault = true; - - describe('inline implementation', () => { - testDockblockHandler( - ` - React.forwardRef((props, ref) => {}); - import React from "react";`, - (src) => - parse - .statement(src, -2) - .get('expression') as NodePath, - ); - - testImports( - `import React from 'react'; - export default React.forwardRef((props, ref) => {});`, - 'RefComponent', - useDefault, - ); - }); - - describe('inline implementation with memo', () => { - testDockblockHandler( - ` - React.memo(React.forwardRef((props, ref) => {})); - import React from "react"; - `, - (src) => - parse - .statement(src, -2) - .get('expression') as NodePath, - ); - - testImports( - ` - export default React.memo(React.forwardRef((props, ref) => {})); - import React from 'react'; - `, - 'RefComponent', - useDefault, - ); - }); - - describe('out of line implementation', () => { - testDockblockHandler( - ` - let Component = (props, ref) => {}; - React.forwardRef(Component); - import React from "react"; - `, - (src) => - parse - .statement(src, -2) - .get('expression') as NodePath, - ); - - testImports( - ` - let Component = (props, ref) => {}; - export default React.forwardRef(Component); - import React from 'react'; - `, - `RefComponent`, - useDefault, - ); - }); - }); -}); diff --git a/packages/react-docgen/src/handlers/__tests__/componentMethodsHandler-test.ts b/packages/react-docgen/src/handlers/__tests__/componentMethodsHandler-test.ts deleted file mode 100644 index 8e67cd1164b..00000000000 --- a/packages/react-docgen/src/handlers/__tests__/componentMethodsHandler-test.ts +++ /dev/null @@ -1,524 +0,0 @@ -import { parse, makeMockImporter } from '../../../tests/utils'; -import componentMethodsHandler from '../componentMethodsHandler.js'; -import DocumentationBuilder from '../../Documentation'; -import type DocumentationMock from '../../__mocks__/Documentation'; -import type { - ArrowFunctionExpression, - AssignmentExpression, - ClassDeclaration, - ExportDefaultDeclaration, - FunctionDeclaration, - FunctionExpression, - VariableDeclaration, -} from '@babel/types'; -import type { NodePath } from '@babel/traverse'; -import type { ComponentNode } from '../../resolver'; -import { beforeEach, describe, expect, test, vi } from 'vitest'; - -vi.mock('../../Documentation.js'); - -describe('componentMethodsHandler', () => { - let documentation: DocumentationBuilder & DocumentationMock; - - beforeEach(() => { - documentation = new DocumentationBuilder() as DocumentationBuilder & - DocumentationMock; - }); - - const mockImporter = makeMockImporter({ - baz: (stmtLast) => - stmtLast(` - export default (foo: string): string => {}; - `).get('declaration'), - - foo: (stmtLast) => - stmtLast(` - export default function(bar: number): number { - return bar; - } - `).get('declaration'), - - doFoo: (stmtLast) => - stmtLast(` - export default () => {}; - `).get('declaration'), - }); - - function testMethodsHandler(definition) { - componentMethodsHandler(documentation, definition); - expect(documentation.methods).toEqual([ - { - name: 'foo', - docblock: 'The foo method', - modifiers: [], - returns: { - type: { name: 'number' }, - }, - params: [ - { - name: 'bar', - optional: false, - type: { name: 'number' }, - }, - ], - }, - { - name: 'baz', - docblock: '"arrow function method"', - modifiers: [], - returns: { - type: { name: 'string' }, - }, - params: [ - { - name: 'foo', - optional: false, - type: { name: 'string' }, - }, - ], - }, - { - name: 'bar', - docblock: 'Static function', - modifiers: ['static'], - returns: null, - params: [], - }, - ]); - } - - describe('useImperativeHandle', () => { - // Other cases BlockScopeBody with return, both assigned and useImperativeHandles - - const methodDefinitions = { - 'direct ObjectExpression': '({ method: () => {} })', - 'regular ReturnStatement': '{x; return { method: () => {} };}', - 'assigned ReturnStatement': '{const r = { method: () => {} }; return r;}', - }; - - Object.entries(methodDefinitions).forEach(([name, code]) => { - describe(name, () => { - test('FunctionExpression Component', () => { - const definition = parse.expressionLast( - `import { useImperativeHandle } from 'react'; - (function () { - useImperativeHandle(ref, () => ${code}); - return
; - });`, - ); - - componentMethodsHandler(documentation, definition); - - expect(documentation.methods).toHaveLength(1); - expect(documentation.methods).toMatchSnapshot(); - }); - - test('FunctionDeclaration Component', () => { - const definition = parse.statementLast( - `import { useImperativeHandle } from 'react'; - function Component() { - useImperativeHandle(ref, () => ${code}); - return
; - }`, - ); - - componentMethodsHandler(documentation, definition); - - expect(documentation.methods).toHaveLength(1); - expect(documentation.methods).toMatchSnapshot(); - }); - - test('ArrowFunctionExpression Component', () => { - const definition = parse.expressionLast( - `import { useImperativeHandle } from 'react'; - (() => { - useImperativeHandle(ref, () => ${code}); - return
; - });`, - ); - - componentMethodsHandler(documentation, definition); - - expect(documentation.methods).toHaveLength(1); - expect(documentation.methods).toMatchSnapshot(); - }); - }); - }); - - test('AssignmentExpression and useImperativeHandle', () => { - const definition = parse - .statement( - `import { useImperativeHandle } from 'react'; - let Component; - Component = function () { - test(); - useImperativeHandle(ref, () => ({ method: () => {} })); - - return
; - }; - Component.other = () => {}; - `, - -2, - ) - .get('expression.right') as NodePath; - - componentMethodsHandler(documentation, definition); - - expect(documentation.methods).toMatchSnapshot(); - }); - - test('VariableDeclaration and useImperativeHandle', () => { - const definition = parse - .statement( - `import { useImperativeHandle } from 'react'; - let Component = function () { - test(); - useImperativeHandle(ref, () => ({ method: () => {} })); - - return
; - }; - Component.other = () => {}; - `, - -2, - ) - .get('declarations.0.init') as NodePath; - - componentMethodsHandler(documentation, definition); - - expect(documentation.methods).toMatchSnapshot(); - }); - }); - - test('extracts the documentation for an ObjectExpression', () => { - const src = ` - { - /** - * The foo method - */ - foo(bar: number): number { - return bar; - }, - /** - * "arrow function method" - */ - baz: (foo: string): string => {}, - statics: { - /** - * Static function - */ - bar() {} - }, - state: { - foo: 'foo', - }, - componentDidMount() {}, - render() { - return null; - }, - } - `; - - testMethodsHandler(parse.expression(src)); - }); - - test('can resolve an imported method on an ObjectExpression', () => { - const src = ` - import baz from 'baz'; - ({ - /** - * The foo method - */ - foo(bar: number): number { - return bar; - }, - /** - * "arrow function method" - */ - baz: baz, - statics: { - /** - * Static function - */ - bar() {} - }, - state: { - foo: 'foo', - }, - componentDidMount() {}, - render() { - return null; - }, - }) - `; - - testMethodsHandler(parse.expressionLast(src, mockImporter)); - }); - - test('extracts the documentation for a ClassDeclaration', () => { - const src = ` - class Test extends React.Component { - /** - * The foo method - */ - foo(bar: number): number { - return bar; - } - - /** - * "arrow function method" - */ - baz = (foo: string): string => {}; - - /** - * Static function - */ - static bar() {} - - state = { - foo: 'foo', - }; - - componentDidMount() {} - - render() { - return null; - } - } - `; - - testMethodsHandler(parse.statement(src)); - }); - - test('can resolve an imported method on a ClassDeclaration', () => { - const src = ` - import baz from 'baz'; - class Test extends React.Component { - /** - * The foo method - */ - foo(bar: number): number { - return bar; - } - - /** - * "arrow function method" - */ - baz = baz; - - /** - * Static function - */ - static bar() {} - - state = { - foo: 'foo', - }; - - componentDidMount() {} - - render() { - return null; - } - } - `; - - testMethodsHandler(parse.statementLast(src, mockImporter)); - }); - - test('should handle and ignore computed methods', () => { - const src = ` - class Test extends React.Component { - /** - * The foo method - */ - [foo](bar: number): number { - return bar; - } - - /** - * Should not show up - */ - [() => {}](bar: number): number { - return bar; - } - - componentDidMount() {} - - render() { - return null; - } - } - `; - - componentMethodsHandler( - documentation, - parse.statement(src), - ); - expect(documentation.methods).toMatchSnapshot(); - }); - - test('resolves imported methods assigned to computed properties', () => { - const src = ` - import foo from 'foo'; - class Test extends React.Component { - /** - * The foo method - */ - [foo] = foo; - - /** - * Should not show up - */ - [() => {}](bar: number): number { - return bar; - } - - componentDidMount() {} - - render() { - return null; - } - } - `; - - componentMethodsHandler( - documentation, - parse.statementLast(src, mockImporter), - ); - expect(documentation.methods).toMatchSnapshot(); - }); - - test('should handle and ignore private properties', () => { - const src = ` - class Test extends React.Component { - #privateProperty = () => { - console.log('Do something'); - } - - componentDidMount() {} - - render() { - return null; - } - } - `; - - componentMethodsHandler( - documentation, - parse.statement(src), - ); - expect((documentation.methods as unknown[]).length).toBe(0); - }); - - describe('function components', () => { - test('no methods', () => { - const src = ` - (props) => {} - `; - - const definition = parse - .statement(src) - .get('expression') as NodePath; - - componentMethodsHandler(documentation, definition); - expect(documentation.methods).toEqual([]); - }); - - test('finds static methods on a component in a variable declaration', () => { - const src = ` - const Test = (props) => {}; - Test.doFoo = () => {}; - Test.doBar = () => {}; - Test.displayName = 'Test'; // Not a method - `; - - componentMethodsHandler( - documentation, - parse - .statement(src) - .get('declarations.0.init') as NodePath, - ); - expect(documentation.methods).toMatchSnapshot(); - }); - - test('resolves imported methods assigned to static properties on a component', () => { - const src = ` - const Test = (props) => {}; - import doFoo from 'doFoo'; - Test.doFoo = doFoo; - `; - - componentMethodsHandler( - documentation, - parse - .statement(src, mockImporter) - .get('declarations.0.init') as NodePath, - ); - expect(documentation.methods).toMatchSnapshot(); - }); - - test('finds static methods on a component in an assignment', () => { - const src = ` - let Test; - Test = (props) => {}; - Test.doFoo = () => {}; - Test.doBar = () => {}; - Test.displayName = 'Test'; // Not a method - `; - - componentMethodsHandler( - documentation, - parse - .statement(src, 1) - .get('expression.right') as NodePath, - ); - expect(documentation.methods).toMatchSnapshot(); - }); - - test('resolves imported methods assigned on a component in an assignment', () => { - const src = ` - let Test; - Test = (props) => {}; - import doFoo from 'doFoo'; - Test.doFoo = doFoo; - `; - - componentMethodsHandler( - documentation, - parse - .statement(src, mockImporter, 1) - .get('expression.right') as NodePath, - ); - expect(documentation.methods).toMatchSnapshot(); - }); - - test('finds static methods on a function declaration', () => { - const src = ` - function Test(props) {} - Test.doFoo = () => {}; - Test.doBar = () => {}; - Test.displayName = 'Test'; // Not a method - `; - - componentMethodsHandler( - documentation, - parse.statement(src), - ); - expect(documentation.methods).toMatchSnapshot(); - }); - - test('resolves imported methods on a function declaration', () => { - const src = ` - function Test(props) {} - import doFoo from 'doFoo'; - Test.doFoo = doFoo; - `; - - componentMethodsHandler( - documentation, - parse.statement(src, mockImporter), - ); - expect(documentation.methods).toMatchSnapshot(); - }); - }); -}); diff --git a/packages/react-docgen/src/handlers/__tests__/componentMethodsJsDocHandler-test.ts b/packages/react-docgen/src/handlers/__tests__/componentMethodsJsDocHandler-test.ts deleted file mode 100644 index c1ab2dc5db0..00000000000 --- a/packages/react-docgen/src/handlers/__tests__/componentMethodsJsDocHandler-test.ts +++ /dev/null @@ -1,105 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import DocumentationBuilder from '../../Documentation'; -import type { ComponentNode } from '../../resolver'; -import type DocumentationMock from '../../__mocks__/Documentation'; -import componentMethodsJsDocHandler from '../componentMethodsJsDocHandler.js'; -import { beforeEach, describe, expect, test } from 'vitest'; - -describe('componentMethodsJsDocHandler', () => { - let documentation: DocumentationBuilder & DocumentationMock; - - beforeEach(() => { - documentation = new DocumentationBuilder() as DocumentationBuilder & - DocumentationMock; - }); - - test('stays the same when no docblock is present', () => { - const methods = [ - { - name: 'foo', - docblock: null, - modifiers: [], - returns: null, - params: [ - { - name: 'test', - type: null, - }, - ], - }, - ]; - - documentation.set('methods', methods); - componentMethodsJsDocHandler(documentation, {} as NodePath); - expect(documentation.get('methods')).toEqual(methods); - }); - - test('adds js doc types when no flow types', () => { - documentation.set('methods', [ - { - name: 'foo', - docblock: ` - @param {string} test - @returns {string} - `, - modifiers: [], - returns: null, - params: [ - { - name: 'test', - type: null, - }, - ], - }, - ]); - componentMethodsJsDocHandler(documentation, {} as NodePath); - expect(documentation.get('methods')).toMatchSnapshot(); - }); - - test('keeps flow types over js doc types', () => { - documentation.set('methods', [ - { - name: 'foo', - docblock: ` - @param {string} test - @returns {string} - `, - modifiers: [], - returns: { - type: { name: 'number' }, - }, - params: [ - { - name: 'test', - type: { name: 'number' }, - }, - ], - }, - ]); - componentMethodsJsDocHandler(documentation, {} as NodePath); - expect(documentation.get('methods')).toMatchSnapshot(); - }); - - test('adds descriptions', () => { - documentation.set('methods', [ - { - name: 'foo', - docblock: ` - The foo method. - @param test The test - @returns The number - `, - modifiers: [], - returns: null, - params: [ - { - name: 'test', - type: null, - }, - ], - }, - ]); - componentMethodsJsDocHandler(documentation, {} as NodePath); - expect(documentation.get('methods')).toMatchSnapshot(); - }); -}); diff --git a/packages/react-docgen/src/handlers/__tests__/defaultPropsHandler-test.ts b/packages/react-docgen/src/handlers/__tests__/defaultPropsHandler-test.ts deleted file mode 100644 index 5675a16494e..00000000000 --- a/packages/react-docgen/src/handlers/__tests__/defaultPropsHandler-test.ts +++ /dev/null @@ -1,702 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { - ArrowFunctionExpression, - CallExpression, - ClassDeclaration, - ClassExpression, - ObjectExpression, - VariableDeclaration, -} from '@babel/types'; -import { parse, makeMockImporter } from '../../../tests/utils'; -import DocumentationBuilder from '../../Documentation'; -import type DocumentationMock from '../../__mocks__/Documentation'; -import defaultPropsHandler from '../defaultPropsHandler.js'; -import { beforeEach, describe, expect, test, vi } from 'vitest'; - -vi.mock('../../Documentation.js'); - -describe('defaultPropsHandler', () => { - let documentation: DocumentationBuilder & DocumentationMock; - - beforeEach(() => { - documentation = new DocumentationBuilder() as DocumentationBuilder & - DocumentationMock; - }); - - const mockImporter = makeMockImporter({ - getDefaultProps: (stmtLast) => - stmtLast(` - import baz from 'baz'; - export default function() { - return { - foo: "bar", - bar: 42, - baz: baz, - abc: {xyz: abc.def, 123: 42} - }; - } - `).get('declaration'), - - baz: (stmtLast) => - stmtLast(` - export default ["foo", "bar"]; - `).get('declaration'), - - other: (stmtLast) => - stmtLast(` - export default { bar: "foo" }; - `).get('declaration'), - - defaultProps: (stmtLast) => - stmtLast(` - export default { - foo: "bar", - bar: 42, - baz: ["foo", "bar"], - abc: {xyz: abc.def, 123: 42} - }; - `).get('declaration'), - }); - - describe('ObjectExpression', () => { - test('should find prop default values that are literals', () => { - const src = ` - { - getDefaultProps: function() { - return { - foo: "bar", - bar: 42, - falseliteral: false, - trueliteral: true, - nullliteral: null, - regex: /./, - bigint: 1n, - baz: ["foo", "bar"], - abc: {xyz: abc.def, 123: 42} - }; - } - } - `; - - defaultPropsHandler( - documentation, - parse.expression(src), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('can resolve object methods', () => { - const src = ` - { - getDefaultProps() { - return { - foo: "bar", - }; - } - } - `; - - defaultPropsHandler( - documentation, - parse.expression(src), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('can resolve declared functions', () => { - const src = ` - function getDefaultProps() { - return { - foo: "bar", - bar: 42, - baz: ["foo", "bar"], - abc: {xyz: abc.def, 123: 42} - }; - } - ({ - getDefaultProps: getDefaultProps - }) - `; - - defaultPropsHandler(documentation, parse.expressionLast(src)); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('should find prop default values that are literals from imported functions', () => { - const src = ` - import getDefaultProps from 'getDefaultProps'; - - ({ - getDefaultProps: getDefaultProps - }) - `; - - defaultPropsHandler( - documentation, - parse.expressionLast(src, mockImporter), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('handles computed properties', () => { - const src = ` - { - getDefaultProps: function() { - return { - foo: "bar", - [bar]: 42, - }; - } - } - `; - - defaultPropsHandler( - documentation, - parse.expression(src), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('handles imported values assigned to computed properties', () => { - const src = ` - import baz from 'baz'; - ({ - getDefaultProps: function() { - return { - foo: "bar", - [bar]: baz, - }; - } - }) - `; - - defaultPropsHandler( - documentation, - parse.expressionLast(src, mockImporter), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('ignores complex computed properties', () => { - const src = ` - ({ - getDefaultProps: function() { - return { - foo: "bar", - [() => {}]: 42, - }; - } - }) - `; - - defaultPropsHandler(documentation, parse.expressionLast(src)); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('ignores imported values assigned to complex computed properties', () => { - const src = ` - import baz from 'baz'; - ({ - getDefaultProps: function() { - return { - foo: "bar", - [() => {}]: baz, - }; - } - }) - `; - - defaultPropsHandler( - documentation, - parse.expressionLast(src, mockImporter), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('resolves local spreads', () => { - const src = ` - const other = { bar: "foo" }; - - ({ - getDefaultProps: function() { - return { - foo: "bar", - ...other, - }; - } - }) - `; - - defaultPropsHandler(documentation, parse.expressionLast(src)); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('resolves imported spreads', () => { - const src = ` - import other from 'other'; - ({ - getDefaultProps: function() { - return { - foo: "bar", - ...other, - }; - } - }) - `; - - defaultPropsHandler( - documentation, - parse.expressionLast(src, mockImporter), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - }); - - describe('ClassDeclaration with static defaultProps', () => { - test('should find prop default values that are literals', () => { - const src = ` - class Foo { - static defaultProps = { - foo: "bar", - bar: 42, - baz: ["foo", "bar"], - abc: {xyz: abc.def, 123: 42} - }; - } - `; - - defaultPropsHandler( - documentation, - parse.statement(src), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('should find prop default values that are literals', () => { - const src = ` - class Foo { - static get defaultProps() { - return { - foo: "bar", - }; - } - } - `; - - defaultPropsHandler( - documentation, - parse.statement(src), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('resolves imported values assigned as default props', () => { - const src = ` - import defaultProps from 'defaultProps'; - class Foo { - static defaultProps = defaultProps; - } - `; - - defaultPropsHandler( - documentation, - parse.statementLast(src, mockImporter), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('should resolve local spreads', () => { - const src = ` - const other = { bar: "foo" }; - - class Foo { - static defaultProps = { - foo: "bar", - ...other - }; - } - `; - - defaultPropsHandler(documentation, parse.statementLast(src)); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('resolves imported spreads', () => { - const src = ` - import other from 'other'; - class Foo { - static defaultProps = { - foo: "bar", - ...other - }; - } - `; - - defaultPropsHandler( - documentation, - parse.statementLast(src, mockImporter), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('should find prop default values that are imported variables', () => { - const src = ` - import ImportedComponent from './ImportedComponent.js'; - - class Foo { - static defaultProps = { - foo: ImportedComponent, - }; - } - `; - - defaultPropsHandler(documentation, parse.statementLast(src)); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('can resolve default props that are imported given a custom importer', () => { - const src = ` - import baz from 'baz'; - - class Foo { - static defaultProps = { - baz: baz, - }; - } - `; - - defaultPropsHandler( - documentation, - parse.statementLast(src, mockImporter), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - }); - - describe('ClassExpression with static defaultProps', () => { - test('should find prop default values that are literals', () => { - const src = ` - var Bar = class { - static defaultProps = { - foo: "bar", - bar: 42, - baz: ["foo", "bar"], - abc: {xyz: abc.def, 123: 42} - }; - }`; - - defaultPropsHandler( - documentation, - parse - .statement(src) - .get('declarations.0.init') as NodePath, - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('resolves imported values assigned as default props', () => { - const src = ` - import defaultProps from 'defaultProps'; - var Bar = class { - static defaultProps = defaultProps; - } - `; - - defaultPropsHandler( - documentation, - parse - .statementLast(src, mockImporter) - .get('declarations.0.init') as NodePath, - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - }); - - test('should only consider Property nodes, not e.g. spread properties', () => { - const src = ` - { - getDefaultProps: function() { - return { - ...Foo.bar, - bar: 42, - }; - } - } - `; - const definition = parse.expression(src); - - expect(() => defaultPropsHandler(documentation, definition)).not.toThrow(); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('can have an importer that resolves spread properties', () => { - const src = ` - import Props from 'defaultProps'; - ({ - getDefaultProps: function() { - return { - ...Props.abc, - bar: 42, - }; - } - }) - `; - const definition = parse.expressionLast( - src, - mockImporter, - ); - - expect(() => defaultPropsHandler(documentation, definition)).not.toThrow(); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - describe('Functional components with default params', () => { - test('should find default props that are literals', () => { - const src = ` - ({ - foo = "bar", - bar = 42, - baz = ["foo", "bar"], - abc = {xyz: abc.def, 123: 42} - }) =>
- `; - - defaultPropsHandler(documentation, parse.expressionLast(src)); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('can use imported values as default props', () => { - const src = ` - import baz from 'baz'; - ({ - bar = baz, - }) =>
- `; - - defaultPropsHandler( - documentation, - parse.expressionLast(src, mockImporter), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('should override with defaultProps if available', () => { - const src = ` - var Foo = ({ - foo = "bar", - bar = 42, - baz = ["foo", "bar"], - abc = 'test' - }) =>
- Foo.defaultProps = { abc: {xyz: abc.def, 123: 42} }; - `; - - defaultPropsHandler( - documentation, - parse - .statement(src) - .get('declarations.0.init') as NodePath, - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('overrides with imported defaultProps', () => { - const src = ` - import other from 'other'; - var Foo = ({ - bar = 42, - }) =>
- Foo.defaultProps = other; - `; - - defaultPropsHandler( - documentation, - parse - .statement(src, mockImporter, 1) - .get('declarations.0.init') as NodePath, - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('resolves local spreads', () => { - const src = ` - const other = { bar: "foo" }; - var Foo = (props) =>
- Foo.defaultProps = { foo: "bar", ...other }; - `; - - defaultPropsHandler( - documentation, - parse - .statement(src, 1) - .get('declarations.0.init') as NodePath, - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('resolves imported spreads', () => { - const src = ` - import other from 'other'; - var Foo = (props) =>
- Foo.defaultProps = { foo: "bar", ...other }; - `; - - defaultPropsHandler( - documentation, - parse - .statement(src, mockImporter, 1) - .get('declarations.0.init') as NodePath, - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('should work with aliases', () => { - const src = ` - ({ - foo = "bar", - bar = 42, - baz = ["foo", "bar"], - abc: defg = {xyz: abc.def, 123: 42} - }) =>
- `; - - defaultPropsHandler( - documentation, - parse.expressionLast(src), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('allows imported defaults to be aliased', () => { - const src = ` - import baz from 'baz'; - ({ - foo: bar = baz, - }) =>
- `; - - defaultPropsHandler( - documentation, - parse.expressionLast(src, mockImporter), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('should find prop default values that are imported variables', () => { - const src = ` - import ImportedComponent from './ImportedComponent.js'; - - ({ - foo = ImportedComponent, - }) =>
- `; - - defaultPropsHandler( - documentation, - parse.expressionLast(src), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('should work with no defaults', () => { - const src = `({ foo }) =>
`; - - defaultPropsHandler( - documentation, - parse.expressionLast(src), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - }); - - describe('forwardRef', () => { - test('resolves default props in the parameters', () => { - const src = ` - import React from 'react'; - React.forwardRef(({ foo = 'bar' }, ref) =>
{foo}
); - `; - - defaultPropsHandler( - documentation, - parse.expressionLast(src), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('resolves imported default props in the parameters', () => { - const src = ` - import baz from 'baz'; - import React from 'react'; - React.forwardRef(({ bar = baz }, ref) =>
{bar}
); - `; - - defaultPropsHandler( - documentation, - parse.expressionLast(src, mockImporter), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('resolves defaultProps', () => { - const src = ` - import React from 'react'; - const Component = React.forwardRef(({ foo }, ref) =>
{foo}
); - Component.defaultProps = { foo: 'baz' }; - `; - - defaultPropsHandler( - documentation, - parse - .statement(src, 1) - .get('declarations.0.init') as NodePath, - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('resolves imported defaultProps', () => { - const src = ` - import other from 'other'; - import React from 'react'; - const Component = React.forwardRef(({ bar }, ref) =>
{bar}
); - Component.defaultProps = other; - `; - - defaultPropsHandler( - documentation, - parse - .statement(src, mockImporter, 2) - .get('declarations.0.init') as NodePath, - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('resolves when the function is not inline', () => { - const src = ` - import React from 'react'; - const ComponentImpl = ({ foo = 'bar' }, ref) =>
{foo}
; - React.forwardRef(ComponentImpl); - `; - - defaultPropsHandler( - documentation, - parse.expressionLast(src), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('also resolves imports when the function is not inline', () => { - const src = ` - import baz from 'baz'; - import React from 'react'; - const ComponentImpl = ({ bar = baz }, ref) =>
{bar}
; - React.forwardRef(ComponentImpl); - `; - - defaultPropsHandler( - documentation, - parse.expressionLast(src, mockImporter), - ); - expect(documentation.descriptors).toMatchSnapshot(); - }); - }); -}); diff --git a/packages/react-docgen/src/handlers/__tests__/displayNameHandler-test.ts b/packages/react-docgen/src/handlers/__tests__/displayNameHandler-test.ts deleted file mode 100644 index d1ea7485d01..00000000000 --- a/packages/react-docgen/src/handlers/__tests__/displayNameHandler-test.ts +++ /dev/null @@ -1,649 +0,0 @@ -import { parse, makeMockImporter } from '../../../tests/utils'; -import DocumentationBuilder from '../../Documentation'; -import displayNameHandler from '../displayNameHandler.js'; -import type DocumentationMock from '../../__mocks__/Documentation'; -import type { - ArrowFunctionExpression, - ClassDeclaration, - ExportDefaultDeclaration, - FunctionDeclaration, - FunctionExpression, - ObjectExpression, - VariableDeclaration, -} from '@babel/types'; -import type { NodePath } from '@babel/traverse'; -import { beforeEach, describe, expect, test, vi } from 'vitest'; - -vi.mock('../../Documentation.js'); - -describe('defaultPropsHandler', () => { - let documentation: DocumentationBuilder & DocumentationMock; - - beforeEach(() => { - documentation = new DocumentationBuilder() as DocumentationBuilder & - DocumentationMock; - }); - - const mockImporter = makeMockImporter({ - foobarbaz: (stmt) => - stmt(` - export default "FooBarBaz" - `).get('declaration'), - - foo: (stmt) => - stmt(` - export default {bar: 'baz'}; - `).get('declaration'), - - bar: (stmt) => - stmt(` - export default {baz: 'foo'}; - `).get('declaration'), - }); - - test('extracts the displayName', () => { - const definition = parse.expression( - '{displayName: "FooBar"}', - ); - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('FooBar'); - }); - - test('extracts the imported displayName', () => { - const definition = parse.expressionLast( - `import foobarbaz from 'foobarbaz'; - ({displayName: foobarbaz});`, - mockImporter, - ); - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('FooBarBaz'); - }); - - test('resolves identifiers', () => { - const definition = parse.expressionLast( - `var name = 'abc'; - ({displayName: name})`, - ); - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('abc'); - }); - - test('resolves imported identifiers', () => { - const definition = parse.expressionLast( - `import foobarbaz from 'foobarbaz'; - var name = foobarbaz; - ({displayName: name})`, - mockImporter, - ); - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('FooBarBaz'); - }); - - test('can resolve non-literal names with appropriate importer', () => { - const definition = parse.expressionLast( - `import foo from 'foo'; - ({displayName: foo.bar});`, - mockImporter, - ); - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('baz'); - }); - - test('ignores non-literal names', () => { - const definition = parse.expression( - '{displayName: foo.bar}', - ); - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).not.toBeDefined(); - }); - - describe('ClassDeclaration', () => { - test('considers the class name', () => { - const definition = parse.statement(`class Foo {}`); - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Foo'); - }); - - test('does not crash if no name', () => { - const definition = parse - .statement(`export default class {}`) - .get('declaration') as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBeUndefined(); - }); - - test('resolves identifiers', () => { - const definition = parse.statement(` - class Foo { - static displayName = name; - } - var name = 'xyz'; - `); - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('xyz'); - }); - - test('resolves imported identifiers', () => { - const definition = parse.statement( - ` - class Foo { - static displayName = name; - } - import foobarbaz from 'foobarbaz'; - var name = foobarbaz; - `, - mockImporter, - ); - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('FooBarBaz'); - }); - - test('resolves imported displayName', () => { - const definition = parse.statement( - ` - class Foo { - static displayName = foobarbaz; - } - import foobarbaz from 'foobarbaz'; - `, - mockImporter, - ); - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('FooBarBaz'); - }); - - test('ignores non-literal names', () => { - const definition = parse.statement(` - class Foo { - static displayName = foo.bar; - } - `); - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBeUndefined(); - }); - - test('can resolve non-literal names with appropriate importer', () => { - const definition = parse.statement( - ` - class Foo { - static displayName = bar.baz; - } - import bar from 'bar'; - `, - mockImporter, - ); - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('foo'); - }); - - test('considers a static displayName class property', () => { - const definition = parse.statement(` - class Foo { - static displayName = 'foo'; - } - `); - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('foo'); - }); - - test('considers static displayName getter', () => { - const definition = parse.statement(` - class Foo { - static get displayName() { - return 'foo'; - } - } - `); - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('foo'); - }); - - test('considers static displayName property with function expression', () => { - const definition = parse.statement(` - class Foo { - static displayName = function() { - return 'foo'; - } - } - `); - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('foo'); - }); - - test('considers static displayName property with function declaration', () => { - const definition = parse.statement(` - class Foo { - static displayName = displayName; - } - function displayName() { - return 'foo'; - } - `); - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('foo'); - }); - - test('resolves variables in displayName getter', () => { - const definition = parse.statement(` - class Foo { - static get displayName() { - return abc; - } - } - const abc = 'bar'; - `); - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('bar'); - }); - - test('resolves imported Identifier in displayName getter', () => { - const definition = parse.statement( - ` - class Foo { - static get displayName() { - return foobarbaz; - } - } - import foobarbaz from 'foobarbaz'; - `, - mockImporter, - ); - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('FooBarBaz'); - }); - - test('resolves imported MemberExpression in displayName getter', () => { - const definition = parse.statement( - ` - class Foo { - static get displayName() { - return foo.bar; - } - } - import foo from 'foo'; - `, - mockImporter, - ); - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('baz'); - }); - }); - - describe('FunctionDeclaration', () => { - test('considers the function name', () => { - const definition = - parse.statement('function Foo () {}'); - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Foo'); - }); - - test('does not crash if no name', () => { - const definition = parse - .statement(`export default function () {}`) - .get('declaration') as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBeUndefined(); - }); - - test('considers a static displayName object property', () => { - const definition = parse.statement(` - function Foo () {} - Foo.displayName = 'Bar'; - `); - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Bar'); - }); - - test('resolves variable assigned to displayName object property', () => { - const definition = parse.statement(` - function Foo () {} - Foo.displayName = bar; - var bar = 'Bar'; - `); - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('Bar'); - }); - - test('resolves imported Identifier assigned to displayName object property', () => { - const definition = parse.statement( - ` - function Foo () {} - import foobarbaz from 'foobarbaz'; - Foo.displayName = foobarbaz; - `, - mockImporter, - ); - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('FooBarBaz'); - }); - - test('resolves imported MemberExpression assigned to displayName object property', () => { - const definition = parse.statement( - ` - function Foo () {} - import foo from 'foo'; - Foo.displayName = foo.bar; - `, - mockImporter, - ); - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('baz'); - }); - }); - - describe('FunctionExpression', () => { - test('considers the variable name', () => { - const definition = parse - .statement('var Foo = function () {};') - .get('declarations.0.init') as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Foo'); - }); - - test('considers the variable name on assign', () => { - const definition = parse - .statement('Foo = function () {};') - .get('expression.right') as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Foo'); - }); - - test('considers a static displayName object property over variable name', () => { - const definition = parse - .statement( - ` - var Foo = function () {}; - Foo.displayName = 'Bar'; - `, - ) - .get('declarations.0.init') as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Bar'); - }); - - test('resolves variable assigned to displayName object property over variable name', () => { - const definition = parse - .statement( - ` - var Foo = function () {}; - Foo.displayName = bar; - var bar = 'Bar'; - `, - ) - .get('declarations.0.init') as NodePath; - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('Bar'); - }); - - test('resolves imported Identifier assigned to displayName object property over variable name', () => { - const definition = parse - .statement( - ` - var Foo = function () {}; - import foobarbaz from 'foobarbaz'; - Foo.displayName = foobarbaz; - `, - mockImporter, - ) - .get('declarations.0.init') as NodePath; - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('FooBarBaz'); - }); - - test('resolves imported MemberExpression assigned to displayName object property over variable name', () => { - const definition = parse - .statement( - ` - var Foo = function () {}; - import foo from 'foo'; - Foo.displayName = foo.bar; - `, - mockImporter, - ) - .get('declarations.0.init') as NodePath; - - displayNameHandler(documentation, definition); - expect(documentation.displayName).toBe('baz'); - }); - }); - - describe('ArrowFunctionExpression', () => { - test('considers the variable name', () => { - const definition = parse - .statement('var Foo = () => {};') - .get('declarations.0.init') as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Foo'); - }); - - test('considers the variable name even if wrapped', () => { - const definition = parse - .statement('var Foo = React.forwardRef(() => {});') - .get( - 'declarations.0.init.arguments.0', - ) as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Foo'); - }); - - test('considers the variable name when handling forwardRef', () => { - const definition = parse - .statement( - ` - var Foo = React.forwardRef(() => {}); - import React from "react"; - `, - ) - .get('declarations.0.init') as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Foo'); - }); - - test('considers the variable name on assign', () => { - const definition = parse - .statement('Foo = () => {};') - .get('expression.right') as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Foo'); - }); - - test('considers the variable name on assign even if wrapped', () => { - const definition = parse - .statement('Foo = React.forwardRef(() => {});') - .get( - 'expression.right.arguments.0', - ) as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Foo'); - }); - - test('considers the variable name on assign when handling forwardRef call', () => { - const definition = parse - .statement( - ` - Foo = React.forwardRef(() => {}); - import React from "react"; - `, - ) - .get('expression.right') as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Foo'); - }); - - test('considers a static displayName object property over variable name', () => { - const definition = parse - .statement( - ` - var Foo = () => {}; - Foo.displayName = 'Bar'; - `, - ) - .get('declarations.0.init') as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Bar'); - }); - - test('resolves a variable assigned to displayName object property over variable name', () => { - const definition = parse - .statement( - ` - var Foo = () => {}; - Foo.displayName = bar; - var bar = 'Bar'; - `, - ) - .get('declarations.0.init') as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Bar'); - }); - - test('resolves imported Identifier assigned to displayName object property over variable name', () => { - const definition = parse - .statement( - ` - var Foo = () => {}; - import foobarbaz from 'foobarbaz'; - Foo.displayName = foobarbaz; - `, - mockImporter, - ) - .get('declarations.0.init') as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('FooBarBaz'); - }); - - test('resolves imported MemberExpression assigned to displayName object property over variable name', () => { - const definition = parse - .statement( - ` - var Foo = () => {}; - import foo from 'foo'; - Foo.displayName = foo.bar; - `, - mockImporter, - ) - .get('declarations.0.init') as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('baz'); - }); - - test('considers a static displayName object property over variable name even if wrapped', () => { - const definition = parse - .statement( - ` - var Foo = React.forwardRef(() => {}); - Foo.displayName = 'Bar'; - `, - ) - .get( - 'declarations.0.init.arguments.0', - ) as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Bar'); - }); - - test('resolves a variable assigned to displayName object property over variable name even if wrapped', () => { - const definition = parse - .statement( - ` - var Foo = React.forwardRef(() => {}); - Foo.displayName = bar; - var bar = 'Bar'; - `, - ) - .get( - 'declarations.0.init.arguments.0', - ) as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('Bar'); - }); - - test('resolves imported Identifier assigned to displayName object property over variable name even if wrapped', () => { - const definition = parse - .statement( - ` - var Foo = React.forwardRef(() => {}); - import foobarbaz from 'foobarbaz'; - Foo.displayName = foobarbaz; - `, - mockImporter, - ) - .get( - 'declarations.0.init.arguments.0', - ) as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('FooBarBaz'); - }); - - test('resolves imported MemberExpression assigned to displayName object property over variable name even if wrapped', () => { - const definition = parse - .statement( - ` - var Foo = React.forwardRef(() => {}); - import foo from 'foo'; - Foo.displayName = foo.bar; - `, - mockImporter, - ) - .get( - 'declarations.0.init.arguments.0', - ) as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).toBe('baz'); - }); - - test('ignores assignment to non-literal/identifier', () => { - const definition = parse - .statement('Foo.Bar = () => {};') - .get('expression.right') as NodePath; - - expect(() => displayNameHandler(documentation, definition)).not.toThrow(); - expect(documentation.displayName).not.toBeDefined(); - }); - }); -}); diff --git a/packages/react-docgen/src/handlers/__tests__/propDocblockHandler-test.ts b/packages/react-docgen/src/handlers/__tests__/propDocblockHandler-test.ts deleted file mode 100644 index 278dc78cdee..00000000000 --- a/packages/react-docgen/src/handlers/__tests__/propDocblockHandler-test.ts +++ /dev/null @@ -1,279 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { ClassDeclaration, ObjectExpression } from '@babel/types'; -import { parse, makeMockImporter, noopImporter } from '../../../tests/utils'; -import DocumentationBuilder from '../../Documentation'; -import type { Importer } from '../../importer'; -import type { ComponentNode } from '../../resolver'; -import type DocumentationMock from '../../__mocks__/Documentation'; -import propDocblockHandler from '../propDocblockHandler.js'; -import { beforeEach, describe, expect, test, vi } from 'vitest'; - -vi.mock('../../Documentation.js'); - -describe('propDocblockHandler', () => { - let documentation: DocumentationBuilder & DocumentationMock; - - beforeEach(() => { - documentation = new DocumentationBuilder() as DocumentationBuilder & - DocumentationMock; - }); - - const mockImporter = makeMockImporter({ - props: (stmtLast) => - stmtLast(` - export default { - /** - * A comment on imported props - */ - foo: Prop.bool, - }; - `).get('declaration'), - }); - - function testDocBlockHandler( - getSrc: (src: string) => string, - parseSrc: (src: string, importer?: Importer) => NodePath, - ) { - test('finds docblocks for prop types', () => { - const definition = parseSrc( - getSrc( - `{ - /** - * Foo comment - */ - foo: Prop.bool, - /** - * Bar comment - */ - bar: Prop.bool, - }`, - ), - ); - - propDocblockHandler(documentation, definition); - expect(documentation.descriptors).toEqual({ - foo: { - description: 'Foo comment', - }, - bar: { - description: 'Bar comment', - }, - }); - }); - - test('can handle multline comments', () => { - const definition = parseSrc( - getSrc( - `{ - /** - * Foo comment with - * many lines! - * - * even with empty lines in between - */ - foo: Prop.bool, - }`, - ), - ); - - propDocblockHandler(documentation, definition); - expect(documentation.descriptors).toEqual({ - foo: { - description: - 'Foo comment with\nmany lines!\n\neven with empty lines in between', - }, - }); - }); - - test('ignores non-docblock comments', () => { - const definition = parseSrc( - getSrc( - `{ - /** - * Foo comment - */ - // TODO: remove this comment - foo: Prop.bool, - /** - * Bar comment - */ - /* This is not a doc comment */ - bar: Prop.bool, - }`, - ), - ); - - propDocblockHandler(documentation, definition); - expect(documentation.descriptors).toEqual({ - foo: { - description: 'Foo comment', - }, - bar: { - description: 'Bar comment', - }, - }); - }); - - test('only considers the comment with the property below it', () => { - const definition = parseSrc( - getSrc( - `{ - /** - * Foo comment - */ - foo: Prop.bool, - bar: Prop.bool, - }`, - ), - ); - - propDocblockHandler(documentation, definition); - expect(documentation.descriptors).toEqual({ - foo: { - description: 'Foo comment', - }, - bar: { - description: '', - }, - }); - }); - - test('understands and ignores the spread operator', () => { - const definition = parseSrc( - getSrc( - `{ - ...Bar.propTypes, - /** - * Foo comment - */ - foo: Prop.bool, - }`, - ), - ); - - propDocblockHandler(documentation, definition); - expect(documentation.descriptors).toEqual({ - foo: { - description: 'Foo comment', - }, - }); - }); - - test('resolves variables', () => { - const definition = parseSrc(` - ${getSrc('Props')} - var Props = { - /** - * Foo comment - */ - foo: Prop.bool, - }; - `); - - propDocblockHandler(documentation, definition); - expect(documentation.descriptors).toEqual({ - foo: { - description: 'Foo comment', - }, - }); - }); - - test('resolves imported variables', () => { - const definition = parseSrc( - ` - ${getSrc('Props')} - import Props from 'props'; - `, - mockImporter, - ); - - propDocblockHandler(documentation, definition); - expect(documentation.descriptors).toEqual({ - foo: { - description: 'A comment on imported props', - }, - }); - }); - - test('resolves imported variables that are spread', () => { - const definition = parseSrc( - ` - ${getSrc('Props')} - import ExtraProps from 'props'; - var Props = { - ...ExtraProps, - /** - * Bar comment - */ - bar: Prop.bool, - } - `, - mockImporter, - ); - - propDocblockHandler(documentation, definition); - expect(documentation.descriptors).toEqual({ - foo: { - description: 'A comment on imported props', - }, - bar: { - description: 'Bar comment', - }, - }); - }); - } - - describe('React.createClass', () => { - testDocBlockHandler( - (propTypesSrc) => `({propTypes: ${propTypesSrc}})`, - (src, importer = noopImporter) => - parse - .statement(src, importer) - .get('expression') as NodePath, - ); - }); - - describe('ClassDefinition', () => { - describe('class property', () => { - testDocBlockHandler( - (propTypesSrc) => ` - class Foo{ - static propTypes = ${propTypesSrc}; - } - `, - (src, importer = noopImporter) => parse.statement(src, importer), - ); - }); - - describe('static getter', () => { - testDocBlockHandler( - (propTypesSrc) => ` - class Foo{ - static get propTypes() { - return ${propTypesSrc}; - } - } - `, - (src, importer = noopImporter) => parse.statement(src, importer), - ); - }); - }); - - describe('does not error if propTypes cannot be found', () => { - test('ObjectExpression', () => { - const definition = parse.expression('{fooBar: 42}'); - - expect(() => - propDocblockHandler(documentation, definition), - ).not.toThrow(); - }); - - test('ClassDeclaration', () => { - const definition = parse.statement('class Foo {}'); - - expect(() => - propDocblockHandler(documentation, definition), - ).not.toThrow(); - }); - }); -}); diff --git a/packages/react-docgen/src/handlers/__tests__/propTypeCompositionHandler-test.ts b/packages/react-docgen/src/handlers/__tests__/propTypeCompositionHandler-test.ts deleted file mode 100644 index c527a8cb028..00000000000 --- a/packages/react-docgen/src/handlers/__tests__/propTypeCompositionHandler-test.ts +++ /dev/null @@ -1,175 +0,0 @@ -import { parse, makeMockImporter, noopImporter } from '../../../tests/utils'; -import propTypeCompositionHandler from '../propTypeCompositionHandler.js'; -import DocumentationBuilder from '../../Documentation'; -import type DocumentationMock from '../../__mocks__/Documentation'; -import type { NodePath } from '@babel/traverse'; -import type { Importer } from '../../importer'; -import type { ClassDeclaration, ObjectExpression } from '@babel/types'; -import type { ComponentNode } from '../../resolver'; -import { beforeEach, describe, expect, test, vi } from 'vitest'; - -vi.mock('../../Documentation.js'); -vi.mock('../../utils/getPropType.js', () => () => ({})); - -describe('propTypeCompositionHandler', () => { - let documentation: DocumentationBuilder & DocumentationMock; - - beforeEach(() => { - documentation = new DocumentationBuilder() as DocumentationBuilder & - DocumentationMock; - }); - - const mockImporter = makeMockImporter({ - 'Foo.react': (stmtLast) => - stmtLast(` - function Component() {} - Component.propTypes = { - foo: 'bar' - }; - export default Component; - `).get('declaration'), - - SharedProps: (stmtLast) => - stmtLast(` - export default { - bar: 'baz' - }; - `).get('declaration'), - }); - - function testCompositionHandler( - getSrc: (src: string) => string, - parseSrc: (src: string, importer?: Importer) => NodePath, - ) { - test('understands assignment from module', () => { - let definition = parseSrc(` - ${getSrc('Foo.propTypes')} - var Foo = require("Foo.react"); - `); - - propTypeCompositionHandler(documentation, definition); - expect(documentation.composes).toEqual(['Foo.react']); - - documentation = new DocumentationBuilder() as DocumentationBuilder & - DocumentationMock; - definition = parseSrc(` - ${getSrc('SharedProps')} - var SharedProps = require("SharedProps"); - `); - - propTypeCompositionHandler(documentation, definition); - expect(documentation.composes).toEqual(['SharedProps']); - }); - - test('understands the spread operator', () => { - const definitionSrc = getSrc( - `{ - ...Foo.propTypes, - ...SharedProps, - }`, - ); - const definition = parseSrc(` - ${definitionSrc} - var Foo = require("Foo.react"); - var SharedProps = require("SharedProps"); - `); - - propTypeCompositionHandler(documentation, definition); - expect(documentation.composes).toEqual(['Foo.react', 'SharedProps']); - }); - - test('does not add any composes if spreads can be fully resolved with the importer', () => { - const definitionSrc = getSrc( - `{ - ...Foo.propTypes, - ...SharedProps, - }`, - ); - const definition = parseSrc( - ` - ${definitionSrc} - import Foo from "Foo.react"; - import SharedProps from "SharedProps"; - `, - mockImporter, - ); - - propTypeCompositionHandler(documentation, definition); - expect(documentation.composes).toEqual([]); - }); - - test('still adds a composes if the importer cannot resolve a value', () => { - const definitionSrc = getSrc( - `{ - ...Foo.propTypes, - ...NotFound, - }`, - ); - const definition = parseSrc( - ` - ${definitionSrc} - import Foo from "Foo.react"; - import NotFound from "NotFound"; - `, - mockImporter, - ); - - propTypeCompositionHandler(documentation, definition); - expect(documentation.composes).toEqual(['NotFound']); - }); - } - - describe('React.createClass', () => { - testCompositionHandler( - (propTypesSrc) => `({propTypes: ${propTypesSrc}})`, - (src, importer = noopImporter) => - parse - .statement(src, importer) - .get('expression') as NodePath, - ); - }); - - describe('class definition', () => { - describe('class properties', () => { - testCompositionHandler( - (propTypesSrc) => ` - class Component { - static propTypes = ${propTypesSrc}; - } - `, - (src, importer = noopImporter) => parse.statement(src, importer), - ); - }); - - describe('static getter', () => { - testCompositionHandler( - (propTypesSrc) => ` - class Component { - static get propTypes() { - return ${propTypesSrc}; - } - } - `, - (src, importer = noopImporter) => parse.statement(src, importer), - ); - }); - }); - - describe('does not error if propTypes cannot be found', () => { - test('ObjectExpression', () => { - const definition = parse.expression('{fooBar: 42}'); - - expect(() => - propTypeCompositionHandler(documentation, definition), - ).not.toThrow(); - }); - - test('ClassDeclaration', () => { - const definition = parse.statement('class Foo {}'); - - expect(() => - propTypeCompositionHandler(documentation, definition), - ).not.toThrow(); - }); - }); -}); diff --git a/packages/react-docgen/src/handlers/__tests__/propTypeHandler-test.ts b/packages/react-docgen/src/handlers/__tests__/propTypeHandler-test.ts deleted file mode 100644 index 37faedb700a..00000000000 --- a/packages/react-docgen/src/handlers/__tests__/propTypeHandler-test.ts +++ /dev/null @@ -1,365 +0,0 @@ -import { parse, makeMockImporter, noopImporter } from '../../../tests/utils'; -import DocumentationBuilder from '../../Documentation'; -import type DocumentationMock from '../../__mocks__/Documentation'; -import { propTypeHandler } from '../propTypeHandler.js'; -import getPropType from '../../utils/getPropType'; -import type { NodePath } from '@babel/traverse'; -import type { Importer } from '../../importer'; -import type { - ArrowFunctionExpression, - ClassDeclaration, - FunctionDeclaration, - ObjectExpression, -} from '@babel/types'; -import type { ComponentNode } from '../../resolver'; -import { beforeEach, describe, expect, test, vi } from 'vitest'; - -const getPropTypeMock = vi.mocked(getPropType); - -vi.mock('../../Documentation.js'); -vi.mock('../../utils/getPropType.js', () => ({ default: vi.fn(() => ({})) })); - -describe('propTypeHandler', () => { - let documentation: DocumentationBuilder & DocumentationMock; - - beforeEach(() => { - documentation = new DocumentationBuilder() as DocumentationBuilder & - DocumentationMock; - }); - - const mockImporter = makeMockImporter({ - props: (stmtLast) => - stmtLast(` - import { PropTypes } from 'react'; - export default {bar: PropTypes.bool}; - `).get('declaration'), - - simpleProp: (stmtLast) => - stmtLast(` - import { PropTypes } from 'react'; - export default PropTypes.array.isRequired; - `).get('declaration'), - - complexProp: (stmtLast) => - stmtLast(` - var prop = PropTypes.oneOfType([PropTypes.number, PropTypes.bool]).isRequired; - import { PropTypes } from 'react'; - export default prop; - `).get('declaration'), - - foo: (stmtLast) => - stmtLast(` - import { PropTypes } from 'react'; - export default PropTypes.bool; - `).get('declaration'), - - bar: (stmtLast) => - stmtLast(` - import { PropTypes } from 'react'; - export default PropTypes.bool; - `).get('declaration'), - - baz: (stmtLast) => - stmtLast(` - import { PropTypes as OtherPropTypes } from 'react'; - export default OtherPropTypes.bool; - `).get('declaration'), - }); - - function template(src: string) { - return ` - ${src} - var React = require('React'); - var PropTypes = React.PropTypes; - var {PropTypes: OtherPropTypes} = React; - `; - } - - function testPropTypes( - getSrc: (src: string) => string, - parseSrc: (src: string, importer?: Importer) => NodePath, - ) { - test('passes the correct argument to getPropType', () => { - const propTypesSrc = `{ - foo: PropTypes.bool, - abc: PropTypes.xyz, - }`; - const definition = parseSrc(getSrc(propTypesSrc)); - - propTypeHandler(documentation, definition); - - expect(getPropTypeMock.mock.calls[0][0]).toMatchSnapshot(); - expect(getPropTypeMock.mock.calls[1][0]).toMatchSnapshot(); - }); - - test('finds definitions via React.PropTypes', () => { - const definition = parseSrc( - getSrc( - `{ - foo: PropTypes.bool, - bar: require("react").PropTypes.bool, - baz: OtherPropTypes.bool, - }`, - ), - ); - - propTypeHandler(documentation, definition); - expect(documentation.descriptors).toEqual({ - foo: { - type: {}, - required: false, - }, - bar: { - type: {}, - required: false, - }, - baz: { - type: {}, - required: false, - }, - }); - }); - - test('finds definitions via the ReactPropTypes module', () => { - const definition = parseSrc( - getSrc( - `{ - foo: require("ReactPropTypes").bool, - }`, - ), - ); - - propTypeHandler(documentation, definition); - expect(documentation.descriptors).toEqual({ - foo: { - type: {}, - required: false, - }, - }); - }); - - test('detects whether a prop is required', () => { - const definition = parseSrc( - getSrc( - `{ - simple_prop: PropTypes.array.isRequired, - complex_prop: - PropTypes.oneOfType([PropTypes.number, PropTypes.bool]).isRequired, - }`, - ), - ); - - propTypeHandler(documentation, definition); - expect(documentation.descriptors).toEqual({ - simple_prop: { - type: {}, - required: true, - }, - complex_prop: { - type: {}, - required: true, - }, - }); - }); - - test('handles computed properties', () => { - const definition = parseSrc( - getSrc( - `{ - [foo]: PropTypes.array.isRequired, - complex_prop: - PropTypes.oneOfType([PropTypes.number, PropTypes.bool]).isRequired, - }`, - ), - ); - - propTypeHandler(documentation, definition); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('ignores complex computed properties', () => { - const definition = parseSrc( - getSrc( - `{ - [() => {}]: PropTypes.array.isRequired, - complex_prop: - PropTypes.oneOfType([PropTypes.number, PropTypes.bool]).isRequired, - }`, - ), - ); - - propTypeHandler(documentation, definition); - expect(documentation.descriptors).toMatchSnapshot(); - }); - - test('only considers definitions from React or ReactPropTypes', () => { - const definition = parseSrc( - getSrc( - `{ - custom_propA: PropTypes.bool, - custom_propB: Prop.bool.isRequired, - }`, - ), - ); - - propTypeHandler(documentation, definition); - expect(documentation.descriptors).toEqual({ - custom_propA: { - type: {}, - required: false, - }, - custom_propB: { - type: { - name: 'custom', - raw: 'Prop.bool.isRequired', - }, - required: false, - }, - }); - }); - - test('resolves variables', () => { - const definitionSrc = getSrc('props'); - const definition = parseSrc(` - ${definitionSrc} - var props = {bar: PropTypes.bool}; - `); - - propTypeHandler(documentation, definition); - expect(documentation.descriptors).toEqual({ - bar: { - type: {}, - required: false, - }, - }); - }); - - test('resolves imported variables', () => { - const definitionSrc = getSrc('props'); - const definition = parseSrc( - ` - ${definitionSrc} - import props from 'props'; - `, - mockImporter, - ); - - propTypeHandler(documentation, definition); - expect(documentation.descriptors).toEqual({ - bar: { - type: {}, - required: false, - }, - }); - }); - - test('can resolve individual imported variables assigned to props', () => { - const definitionSrc = getSrc(`{ - foo: foo, - [bar]: bar, - baz: baz, - simple_prop: simpleProp, - complex_prop: complexProp, - }`); - const definition = parseSrc( - ` - ${definitionSrc} - import foo from 'foo'; - import bar from 'bar'; - import baz from 'baz'; - import simpleProp from 'simpleProp'; - import complexProp from 'complexProp'; - `, - mockImporter, - ); - - propTypeHandler(documentation, definition); - expect(documentation.descriptors).toMatchSnapshot(); - }); - } - - describe('React.createClass', () => { - testPropTypes( - (propTypesSrc) => template(`({propTypes: ${propTypesSrc}})`), - (src, importer = noopImporter) => - parse - .statement(src, importer) - .get('expression') as NodePath, - ); - }); - - describe('class definition', () => { - describe('class property', () => { - testPropTypes( - (propTypesSrc) => - template(` - class Component { - static propTypes = ${propTypesSrc}; - } - `), - (src, importer = noopImporter) => parse.statement(src, importer), - ); - }); - - describe('static getter', () => { - testPropTypes( - (propTypesSrc) => - template(` - class Component { - static get propTypes() { - return ${propTypesSrc}; - } - } - `), - (src, importer = noopImporter) => parse.statement(src, importer), - ); - }); - }); - - describe('stateless component', () => { - testPropTypes( - (propTypesSrc) => - template(` - var Component = (props) =>
; - Component.propTypes = ${propTypesSrc}; - `), - (src, importer = noopImporter) => parse.statement(src, importer), - ); - }); - - describe('does not error if propTypes cannot be found', () => { - test('ObjectExpression', () => { - const definition = parse.expression('{fooBar: 42}'); - - expect(() => propTypeHandler(documentation, definition)).not.toThrow(); - }); - - test('ClassDeclaration', () => { - const definition = parse.statement('class Foo {}'); - - expect(() => propTypeHandler(documentation, definition)).not.toThrow(); - }); - - test('FunctionDeclaration', () => { - const definition = - parse.statement('function Foo() {}'); - - expect(() => propTypeHandler(documentation, definition)).not.toThrow(); - }); - - test('ArrowFunctionExpression', () => { - const definition = parse.expression('() => {}'); - - expect(() => propTypeHandler(documentation, definition)).not.toThrow(); - }); - }); - - // This case is handled by propTypeCompositionHandler - test('does not error if propTypes is a member expression', () => { - const definition = parse.expression( - '{propTypes: Foo.propTypes}', - ); - - expect(() => propTypeHandler(documentation, definition)).not.toThrow(); - }); -}); diff --git a/packages/react-docgen/src/handlers/codeTypeHandler.ts b/packages/react-docgen/src/handlers/codeTypeHandler.ts deleted file mode 100644 index 75310b4b3d8..00000000000 --- a/packages/react-docgen/src/handlers/codeTypeHandler.ts +++ /dev/null @@ -1,127 +0,0 @@ -import type Documentation from '../Documentation.js'; -import { unwrapUtilityType } from '../utils/flowUtilityTypes.js'; -import getFlowType from '../utils/getFlowType.js'; -import getTypeFromReactComponent, { - applyToTypeProperties, -} from '../utils/getTypeFromReactComponent.js'; -import getPropertyName from '../utils/getPropertyName.js'; -import getTSType from '../utils/getTSType.js'; -import type { TypeParameters } from '../utils/getTypeParameters.js'; -import resolveToValue from '../utils/resolveToValue.js'; -import setPropDescription from '../utils/setPropDescription.js'; -import type { NodePath } from '@babel/traverse'; -import type { FlowType } from '@babel/types'; -import type { ComponentNode } from '../resolver/index.js'; -import type { Handler } from './index.js'; - -function setPropDescriptor( - documentation: Documentation, - path: NodePath, - typeParams: TypeParameters | null, -): void { - if (path.isObjectTypeSpreadProperty()) { - const argument = unwrapUtilityType( - path.get('argument'), - ) as NodePath; - - if (argument.isObjectTypeAnnotation()) { - applyToTypeProperties( - documentation, - argument, - (propertyPath, innerTypeParams) => { - setPropDescriptor(documentation, propertyPath, innerTypeParams); - }, - typeParams, - ); - - return; - } - - const id = argument.get('id') as NodePath; - - if (!id.hasNode() || !id.isIdentifier()) { - return; - } - const resolvedPath = resolveToValue(id); - - if (resolvedPath.isTypeAlias()) { - const right = resolvedPath.get('right'); - - applyToTypeProperties( - documentation, - right, - (propertyPath, innerTypeParams) => { - setPropDescriptor(documentation, propertyPath, innerTypeParams); - }, - typeParams, - ); - } else if (!argument.has('typeParameters')) { - documentation.addComposes(id.node.name); - } - } else if (path.isObjectTypeProperty()) { - const type = getFlowType(path.get('value'), typeParams); - const propName = getPropertyName(path); - - if (!propName) return; - - const propDescriptor = documentation.getPropDescriptor(propName); - - propDescriptor.required = !path.node.optional; - propDescriptor.flowType = type; - - // We are doing this here instead of in a different handler - // to not need to duplicate the logic for checking for - // imported types that are spread in to props. - setPropDescription(documentation, path); - } else if (path.isTSPropertySignature()) { - const typeAnnotation = path.get('typeAnnotation'); - - if (!typeAnnotation.hasNode()) { - return; - } - const type = getTSType(typeAnnotation, typeParams); - - const propName = getPropertyName(path); - - if (!propName) return; - - const propDescriptor = documentation.getPropDescriptor(propName); - - propDescriptor.required = !path.node.optional; - propDescriptor.tsType = type; - - // We are doing this here instead of in a different handler - // to not need to duplicate the logic for checking for - // imported types that are spread in to props. - setPropDescription(documentation, path); - } -} - -/** - * This handler tries to find flow and TS Type annotated react components and extract - * its types to the documentation. It also extracts docblock comments which are - * inlined in the type definition. - */ -const codeTypeHandler: Handler = function ( - documentation: Documentation, - componentDefinition: NodePath, -): void { - const typePaths = getTypeFromReactComponent(componentDefinition); - - if (typePaths.length === 0) { - return; - } - - for (const typePath of typePaths) { - applyToTypeProperties( - documentation, - typePath, - (propertyPath, typeParams) => { - setPropDescriptor(documentation, propertyPath, typeParams); - }, - null, - ); - } -}; - -export default codeTypeHandler; diff --git a/packages/react-docgen/src/handlers/componentDocblockHandler.ts b/packages/react-docgen/src/handlers/componentDocblockHandler.ts deleted file mode 100644 index 3720f247ea4..00000000000 --- a/packages/react-docgen/src/handlers/componentDocblockHandler.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type Documentation from '../Documentation.js'; -import { getDocblock } from '../utils/docblock.js'; -import isReactForwardRefCall from '../utils/isReactForwardRefCall.js'; -import resolveToValue from '../utils/resolveToValue.js'; -import type { NodePath } from '@babel/traverse'; -import type { ComponentNode } from '../resolver/index.js'; -import type { Handler } from './index.js'; -import type { Decorator } from '@babel/types'; - -function getDocblockFromComponent(path: NodePath): string | null { - let description: string | null = null; - - if (path.isClassDeclaration() || path.isClassExpression()) { - const decorators = path.get('decorators') as - | Array> - | null - | undefined; - - // If we have a class declaration or expression, then the comment might be - // attached to the last decorator instead as trailing comment. - if (decorators && decorators.length > 0) { - description = getDocblock(decorators[decorators.length - 1]!, true); - } - } - if (description == null) { - // Find parent statement (e.g. var Component = React.createClass();) - let searchPath: NodePath | null = path; - - while (searchPath && !searchPath.isStatement()) { - searchPath = searchPath.parentPath; - } - if (searchPath) { - // If the parent is an export statement, we have to traverse one more up - if ( - searchPath.parentPath.isExportNamedDeclaration() || - searchPath.parentPath.isExportDefaultDeclaration() - ) { - searchPath = searchPath.parentPath; - } - description = getDocblock(searchPath); - } - } - if (!description) { - const searchPath = isReactForwardRefCall(path) - ? path.get('arguments')[0]! - : path; - const inner = resolveToValue(searchPath); - - if (inner.node !== path.node) { - return getDocblockFromComponent(inner); - } - } - - return description; -} - -/** - * Finds the nearest block comment before the component definition. - */ -const componentDocblockHandler: Handler = function ( - documentation: Documentation, - componentDefinition: NodePath, -): void { - documentation.set( - 'description', - getDocblockFromComponent(componentDefinition) || '', - ); -}; - -export default componentDocblockHandler; diff --git a/packages/react-docgen/src/handlers/componentMethodsHandler.ts b/packages/react-docgen/src/handlers/componentMethodsHandler.ts deleted file mode 100644 index bc1bdf2f30d..00000000000 --- a/packages/react-docgen/src/handlers/componentMethodsHandler.ts +++ /dev/null @@ -1,271 +0,0 @@ -import getMemberValuePath from '../utils/getMemberValuePath.js'; -import type { MethodNodePath } from '../utils/getMethodDocumentation.js'; -import getMethodDocumentation from '../utils/getMethodDocumentation.js'; -import isReactComponentClass from '../utils/isReactComponentClass.js'; -import isReactComponentMethod from '../utils/isReactComponentMethod.js'; -import type Documentation from '../Documentation.js'; -import { shallowIgnoreVisitors } from '../utils/traverse.js'; -import resolveToValue from '../utils/resolveToValue.js'; -import type { NodePath, Scope } from '@babel/traverse'; -import { visitors } from '@babel/traverse'; -import type { - AssignmentExpression, - BlockStatement, - Identifier, - ObjectExpression, -} from '@babel/types'; -import type { ComponentNode } from '../resolver/index.js'; -import type { Handler } from './index.js'; -import { - isReactBuiltinCall, - isReactForwardRefCall, - isStatelessComponent, - findFunctionReturn, -} from '../utils/index.js'; - -/** - * The following values/constructs are considered methods: - * - * - Method declarations in classes (except "constructor" and React lifecycle - * methods - * - Public class fields in classes whose value are a functions - * - Object properties whose values are functions - */ -function isMethod(path: NodePath): path is MethodNodePath { - let isProbablyMethod = - (path.isClassMethod() && path.node.kind !== 'constructor') || - path.isObjectMethod(); - - if ( - !isProbablyMethod && - (path.isClassProperty() || path.isObjectProperty()) - ) { - const value = resolveToValue(path.get('value') as NodePath); - - isProbablyMethod = value.isFunction(); - } - - return isProbablyMethod && !isReactComponentMethod(path); -} - -interface TraverseState { - readonly scope: Scope | undefined; - readonly name: string; - methods: Array>; -} - -const explodedVisitors = visitors.explode({ - ...shallowIgnoreVisitors, - - AssignmentExpression: { - enter: function (assignmentPath, state) { - const { name, scope } = state; - const left = assignmentPath.get('left'); - const binding = assignmentPath.scope.getBinding(name); - - if ( - binding && - left.isMemberExpression() && - left.get('object').isIdentifier({ name }) && - binding.scope === scope && - resolveToValue(assignmentPath.get('right')).isFunction() - ) { - state.methods.push(assignmentPath); - } - assignmentPath.skip(); - }, - }, -}); - -interface MethodDefinition { - path: MethodNodePath; - isStatic?: boolean; -} - -interface TraverseImperativeHandleState { - results: MethodNodePath[]; -} - -function isObjectExpression( - path: NodePath, -): path is NodePath { - return path.isObjectExpression(); -} - -const explodedImperativeHandleVisitors = - visitors.explode({ - ...shallowIgnoreVisitors, - - CallExpression: { - enter: function (path, state) { - if (!isReactBuiltinCall(path, 'useImperativeHandle')) { - return path.skip(); - } - - // useImperativeHandle(ref, () => ({ name: () => {}, ...})) - const arg = path.get('arguments')[1]; - - if (!arg || !arg.isFunction()) { - return path.skip(); - } - - const body = resolveToValue(arg.get('body') as NodePath); - - let definition: NodePath | undefined; - - if (body.isObjectExpression()) { - definition = body; - } else { - definition = findFunctionReturn(arg, isObjectExpression); - } - - // We found the object body, now add all of the properties as methods. - definition?.get('properties').forEach((p) => { - if (isMethod(p)) { - state.results.push(p); - } - }); - - path.skip(); - }, - }, - }); - -function findStatelessComponentBody( - componentDefinition: NodePath, -): NodePath | undefined { - if (isStatelessComponent(componentDefinition)) { - const body = componentDefinition.get('body'); - - if (body.isBlockStatement()) { - return body; - } - } else if (isReactForwardRefCall(componentDefinition)) { - const inner = resolveToValue(componentDefinition.get('arguments')[0]!); - - return findStatelessComponentBody(inner); - } - - return undefined; -} - -function findImperativeHandleMethods( - componentDefinition: NodePath, -): MethodDefinition[] { - const body = findStatelessComponentBody(componentDefinition); - - if (!body) { - return []; - } - - const state: TraverseImperativeHandleState = { results: [] }; - - body.traverse(explodedImperativeHandleVisitors, state); - - return state.results.map((p) => ({ path: p })); -} - -function findAssignedMethods( - path: NodePath, - idPath: NodePath, -): MethodDefinition[] { - if (!idPath.hasNode() || !idPath.isIdentifier()) { - return []; - } - - const name = idPath.node.name; - const binding = idPath.scope.getBinding(name); - - if (!binding) { - return []; - } - - const scope = binding.scope; - const state: TraverseState = { - scope, - name, - methods: [], - }; - - path.traverse(explodedVisitors, state); - - return state.methods.map((p) => ({ path: p })); -} - -/** - * Extract all flow types for the methods of a react component. Doesn't - * return any react specific lifecycle methods. - */ -const componentMethodsHandler: Handler = function ( - documentation: Documentation, - componentDefinition: NodePath, -): void { - // Extract all methods from the class or object. - let methodPaths: MethodDefinition[] = []; - const parent = componentDefinition.parentPath; - - if (isReactComponentClass(componentDefinition)) { - methodPaths = ( - componentDefinition - .get('body') - .get('body') - .filter(isMethod) as MethodNodePath[] - ).map((p) => ({ path: p })); - } else if (componentDefinition.isObjectExpression()) { - methodPaths = ( - componentDefinition.get('properties').filter(isMethod) as MethodNodePath[] - ).map((p) => ({ path: p })); - - // Add the statics object properties. - const statics = getMemberValuePath(componentDefinition, 'statics'); - - if (statics && statics.isObjectExpression()) { - statics.get('properties').forEach((property) => { - if (isMethod(property)) { - methodPaths.push({ - path: property, - isStatic: true, - }); - } - }); - } - } else if ( - parent.isVariableDeclarator() && - parent.node.init === componentDefinition.node && - parent.get('id').isIdentifier() - ) { - methodPaths = findAssignedMethods( - parent.scope.path, - parent.get('id') as NodePath, - ); - } else if ( - parent.isAssignmentExpression() && - parent.node.right === componentDefinition.node && - parent.get('left').isIdentifier() - ) { - methodPaths = findAssignedMethods( - parent.scope.path, - parent.get('left') as NodePath, - ); - } else if (componentDefinition.isFunctionDeclaration()) { - methodPaths = findAssignedMethods( - parent.scope.path, - componentDefinition.get('id'), - ); - } - - const imperativeHandles = findImperativeHandleMethods(componentDefinition); - - if (imperativeHandles) { - methodPaths = [...methodPaths, ...imperativeHandles]; - } - - documentation.set( - 'methods', - methodPaths - .map(({ path: p, isStatic }) => getMethodDocumentation(p, { isStatic })) - .filter(Boolean), - ); -}; - -export default componentMethodsHandler; diff --git a/packages/react-docgen/src/handlers/componentMethodsJsDocHandler.ts b/packages/react-docgen/src/handlers/componentMethodsJsDocHandler.ts deleted file mode 100644 index 5f6690fdc7e..00000000000 --- a/packages/react-docgen/src/handlers/componentMethodsJsDocHandler.ts +++ /dev/null @@ -1,69 +0,0 @@ -import parseJsDoc from '../utils/parseJsDoc.js'; -import type { - default as Documentation, - MethodDescriptor, -} from '../Documentation.js'; -import type { Handler } from './index.js'; - -function removeEmpty>(obj: T): T { - return Object.fromEntries( - Object.entries(obj).filter(([, v]) => v != null), - ) as T; -} - -// Merges two objects ignoring null/undefined. -function merge(obj1: null | undefined, obj2: null | undefined): null; -function merge(obj1: T1, obj2: T2): T1 & T2; -function merge( - obj1: Record | null | undefined, - obj2: Record | null | undefined, -): Record | null { - if (obj1 == null && obj2 == null) { - return null; - } - const merged = { - ...removeEmpty(obj1 ?? {}), - ...removeEmpty(obj2 ?? {}), - }; - - return merged; -} -/** - * Extract info from the methods jsdoc blocks. Must be run after - * componentMethodsHandler. - */ -const componentMethodsJsDocHandler: Handler = function ( - documentation: Documentation, -): void { - let methods = documentation.get('methods'); - - if (!methods) { - return; - } - - methods = methods.map((method) => { - if (!method.docblock) { - return method; - } - - const jsDoc = parseJsDoc(method.docblock); - - const returns = merge(jsDoc.returns, method.returns); - const params = method.params.map((param) => { - const jsDocParam = jsDoc.params.find((p) => p.name === param.name); - - return merge(jsDocParam, param); - }); - - return { - ...method, - description: jsDoc.description || null, - returns, - params, - }; - }); - - documentation.set('methods', methods); -}; - -export default componentMethodsJsDocHandler; diff --git a/packages/react-docgen/src/handlers/defaultPropsHandler.ts b/packages/react-docgen/src/handlers/defaultPropsHandler.ts deleted file mode 100644 index af6acac93c0..00000000000 --- a/packages/react-docgen/src/handlers/defaultPropsHandler.ts +++ /dev/null @@ -1,191 +0,0 @@ -import getPropertyName from '../utils/getPropertyName.js'; -import getMemberValuePath from '../utils/getMemberValuePath.js'; -import printValue from '../utils/printValue.js'; -import resolveToValue from '../utils/resolveToValue.js'; -import resolveFunctionDefinitionToReturnValue from '../utils/resolveFunctionDefinitionToReturnValue.js'; -import isReactComponentClass from '../utils/isReactComponentClass.js'; -import isReactForwardRefCall from '../utils/isReactForwardRefCall.js'; -import type Documentation from '../Documentation.js'; -import type { DefaultValueDescriptor } from '../Documentation.js'; -import type { NodePath } from '@babel/traverse'; -import type { - CallExpression, - ObjectMethod, - ObjectProperty, - RestElement, - SpreadElement, -} from '@babel/types'; -import type { - ComponentNode, - StatelessComponentNode, -} from '../resolver/index.js'; -import type { Handler } from './index.js'; - -function getDefaultValue(path: NodePath): DefaultValueDescriptor | null { - let defaultValue: string | undefined; - let resolvedPath = path; - let valuePath = path; - - if (path.isBooleanLiteral()) { - defaultValue = `${path.node.value}`; - } else if (path.isNullLiteral()) { - defaultValue = 'null'; - } else if (path.isLiteral()) { - defaultValue = path.node.extra?.raw as string; - } else { - if (path.isAssignmentPattern()) { - resolvedPath = resolveToValue(path.get('right')); - } else { - resolvedPath = resolveToValue(path); - } - if (resolvedPath.parentPath?.isImportDeclaration() && path.isIdentifier()) { - defaultValue = path.node.name; - } else { - valuePath = resolvedPath; - defaultValue = printValue(resolvedPath); - } - } - if (typeof defaultValue !== 'undefined') { - return { - value: defaultValue, - computed: - valuePath.isCallExpression() || - valuePath.isMemberExpression() || - valuePath.isIdentifier(), - }; - } - - return null; -} - -function getStatelessPropsPath( - componentDefinition: NodePath, -): NodePath | undefined { - let value: NodePath = componentDefinition; - - if (isReactForwardRefCall(componentDefinition)) { - value = resolveToValue(componentDefinition.get('arguments')[0]!); - } - - if (!value.isFunction()) { - return; - } - - return value.get('params')[0]; -} - -function getDefaultPropsPath( - componentDefinition: NodePath, -): NodePath | null { - let defaultPropsPath: NodePath | null = getMemberValuePath( - componentDefinition, - 'defaultProps', - ); - - if (!defaultPropsPath) { - return null; - } - - defaultPropsPath = resolveToValue(defaultPropsPath); - if (!defaultPropsPath) { - return null; - } - - if ( - defaultPropsPath.isFunctionExpression() || - defaultPropsPath.isFunctionDeclaration() || - defaultPropsPath.isClassMethod() || - defaultPropsPath.isObjectMethod() - ) { - // Find the value that is returned from the function and process it if it is - // an object literal. - const returnValue = - resolveFunctionDefinitionToReturnValue(defaultPropsPath); - - if (returnValue && returnValue.isObjectExpression()) { - defaultPropsPath = returnValue; - } - } - - return defaultPropsPath; -} - -function getDefaultValuesFromProps( - properties: Array< - NodePath - >, - documentation: Documentation, - isStateless: boolean, -): void { - properties.forEach((propertyPath) => { - if (propertyPath.isObjectProperty()) { - const propName = getPropertyName(propertyPath); - - if (!propName) return; - - let valuePath = propertyPath.get('value'); - - if (isStateless) { - if (valuePath.isAssignmentPattern()) { - valuePath = valuePath.get('right'); - } else { - // Don't evaluate property if component is functional and the node is not an AssignmentPattern - return; - } - } - - // Initialize the prop descriptor here after the early return from above - const propDescriptor = documentation.getPropDescriptor(propName); - const defaultValue = getDefaultValue(valuePath); - - if (defaultValue) { - propDescriptor.defaultValue = defaultValue; - } - } else if (propertyPath.isSpreadElement()) { - const resolvedValuePath = resolveToValue(propertyPath.get('argument')); - - if (resolvedValuePath.isObjectExpression()) { - getDefaultValuesFromProps( - resolvedValuePath.get('properties'), - documentation, - isStateless, - ); - } - } - }); -} - -const defaultPropsHandler: Handler = function ( - documentation: Documentation, - componentDefinition: NodePath, -): void { - let statelessProps: NodePath | undefined; - const defaultPropsPath = getDefaultPropsPath(componentDefinition); - - /** - * function, lazy, memo, forwardRef etc components can resolve default props as well - */ - if (!isReactComponentClass(componentDefinition)) { - statelessProps = getStatelessPropsPath( - componentDefinition as NodePath, - ); - } - - // Do both statelessProps and defaultProps if both are available so defaultProps can override - if (statelessProps && statelessProps.isObjectPattern()) { - getDefaultValuesFromProps( - statelessProps.get('properties'), - documentation, - true, - ); - } - if (defaultPropsPath && defaultPropsPath.isObjectExpression()) { - getDefaultValuesFromProps( - defaultPropsPath.get('properties'), - documentation, - false, - ); - } -}; - -export default defaultPropsHandler; diff --git a/packages/react-docgen/src/handlers/displayNameHandler.ts b/packages/react-docgen/src/handlers/displayNameHandler.ts deleted file mode 100644 index 09501b80eba..00000000000 --- a/packages/react-docgen/src/handlers/displayNameHandler.ts +++ /dev/null @@ -1,79 +0,0 @@ -import getMemberValuePath from '../utils/getMemberValuePath.js'; -import getNameOrValue from '../utils/getNameOrValue.js'; -import isReactForwardRefCall from '../utils/isReactForwardRefCall.js'; -import resolveToValue from '../utils/resolveToValue.js'; -import resolveFunctionDefinitionToReturnValue from '../utils/resolveFunctionDefinitionToReturnValue.js'; -import type Documentation from '../Documentation.js'; -import type { NodePath } from '@babel/traverse'; -import type { Identifier } from '@babel/types'; -import type { Handler } from './index.js'; -import type { ComponentNode } from '../resolver/index.js'; - -const displayNameHandler: Handler = function ( - documentation: Documentation, - componentDefinition: NodePath, -): void { - let displayNamePath: NodePath | null = getMemberValuePath( - componentDefinition, - 'displayName', - ); - - if (!displayNamePath) { - // Function and class declarations need special treatment. The name of the - // function / class is the displayName - if ( - (componentDefinition.isClassDeclaration() || - componentDefinition.isFunctionDeclaration()) && - componentDefinition.has('id') - ) { - documentation.set( - 'displayName', - getNameOrValue(componentDefinition.get('id') as NodePath), - ); - } else if ( - componentDefinition.isArrowFunctionExpression() || - componentDefinition.isFunctionExpression() || - isReactForwardRefCall(componentDefinition) - ) { - let currentPath: NodePath = componentDefinition; - - while (currentPath.parentPath) { - if (currentPath.parentPath.isVariableDeclarator()) { - documentation.set( - 'displayName', - getNameOrValue(currentPath.parentPath.get('id')), - ); - - return; - } else if (currentPath.parentPath.isAssignmentExpression()) { - const leftPath = currentPath.parentPath.get('left'); - - if (leftPath.isIdentifier() || leftPath.isLiteral()) { - documentation.set('displayName', getNameOrValue(leftPath)); - - return; - } - } - currentPath = currentPath.parentPath; - } - } - - return; - } - displayNamePath = resolveToValue(displayNamePath); - - // If display name is defined as function somehow (getter, property with function) - // we resolve the return value of the function - if (displayNamePath.isFunction()) { - displayNamePath = resolveFunctionDefinitionToReturnValue(displayNamePath); - } - if ( - !displayNamePath || - (!displayNamePath.isStringLiteral() && !displayNamePath.isNumericLiteral()) - ) { - return; - } - documentation.set('displayName', displayNamePath.node.value); -}; - -export default displayNameHandler; diff --git a/packages/react-docgen/src/handlers/index.ts b/packages/react-docgen/src/handlers/index.ts deleted file mode 100644 index 90d1f75dabc..00000000000 --- a/packages/react-docgen/src/handlers/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type Documentation from '../Documentation.js'; -import type { ComponentNode } from '../resolver/index.js'; - -export { default as componentDocblockHandler } from './componentDocblockHandler.js'; -export { default as componentMethodsHandler } from './componentMethodsHandler.js'; -export { default as componentMethodsJsDocHandler } from './componentMethodsJsDocHandler.js'; -export { default as defaultPropsHandler } from './defaultPropsHandler.js'; -export { default as displayNameHandler } from './displayNameHandler.js'; -export { default as codeTypeHandler } from './codeTypeHandler.js'; -export { default as propDocblockHandler } from './propDocblockHandler.js'; -export { default as propTypeCompositionHandler } from './propTypeCompositionHandler.js'; -export { - propTypeHandler, - contextTypeHandler, - childContextTypeHandler, -} from './propTypeHandler.js'; - -export type Handler = ( - documentation: Documentation, - componentDefinition: NodePath, -) => void; diff --git a/packages/react-docgen/src/handlers/propDocblockHandler.ts b/packages/react-docgen/src/handlers/propDocblockHandler.ts deleted file mode 100644 index 8c02bf59cd4..00000000000 --- a/packages/react-docgen/src/handlers/propDocblockHandler.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import getMemberValuePath from '../utils/getMemberValuePath.js'; -import resolveToValue from '../utils/resolveToValue.js'; -import setPropDescription from '../utils/setPropDescription.js'; -import type Documentation from '../Documentation.js'; -import type { ComponentNode } from '../resolver/index.js'; -import type { Handler } from './index.js'; - -function resolveDocumentation( - documentation: Documentation, - path: NodePath, -): void { - if (!path.isObjectExpression()) { - return; - } - - path.get('properties').forEach((propertyPath) => { - if (propertyPath.isSpreadElement()) { - const resolvedValuePath = resolveToValue(propertyPath.get('argument')); - - resolveDocumentation(documentation, resolvedValuePath); - } else if ( - propertyPath.isObjectProperty() || - propertyPath.isObjectMethod() - ) { - setPropDescription(documentation, propertyPath); - } - }); -} - -const propDocblockHandler: Handler = function ( - documentation: Documentation, - componentDefinition: NodePath, -): void { - let propTypesPath: NodePath | null = getMemberValuePath( - componentDefinition, - 'propTypes', - ); - - if (!propTypesPath) { - return; - } - propTypesPath = resolveToValue(propTypesPath); - if (!propTypesPath) { - return; - } - - resolveDocumentation(documentation, propTypesPath); -}; - -export default propDocblockHandler; diff --git a/packages/react-docgen/src/handlers/propTypeCompositionHandler.ts b/packages/react-docgen/src/handlers/propTypeCompositionHandler.ts deleted file mode 100644 index 1031755cd0a..00000000000 --- a/packages/react-docgen/src/handlers/propTypeCompositionHandler.ts +++ /dev/null @@ -1,62 +0,0 @@ -import getMemberValuePath from '../utils/getMemberValuePath.js'; -import resolveToModule from '../utils/resolveToModule.js'; -import resolveToValue from '../utils/resolveToValue.js'; -import type Documentation from '../Documentation.js'; -import type { NodePath } from '@babel/traverse'; -import type { ObjectExpression } from '@babel/types'; -import type { Handler } from './index.js'; -import type { ComponentNode } from '../resolver/index.js'; - -/** - * It resolves the path to its module name and adds it to the "composes" entry - * in the documentation. - */ -function amendComposes(documentation: Documentation, path: NodePath): void { - const moduleName = resolveToModule(path); - - if (moduleName) { - documentation.addComposes(moduleName); - } -} - -function processObjectExpression( - documentation: Documentation, - path: NodePath, -): void { - path.get('properties').forEach((propertyPath) => { - if (propertyPath.isSpreadElement()) { - amendComposes( - documentation, - resolveToValue(propertyPath.get('argument')), - ); - } - }); -} - -const propTypeCompositionHandler: Handler = function ( - documentation: Documentation, - componentDefinition: NodePath, -): void { - let propTypesPath: NodePath | null = getMemberValuePath( - componentDefinition, - 'propTypes', - ); - - if (!propTypesPath) { - return; - } - propTypesPath = resolveToValue(propTypesPath); - if (!propTypesPath) { - return; - } - - if (propTypesPath.isObjectExpression()) { - processObjectExpression(documentation, propTypesPath); - - return; - } - - amendComposes(documentation, propTypesPath); -}; - -export default propTypeCompositionHandler; diff --git a/packages/react-docgen/src/handlers/propTypeHandler.ts b/packages/react-docgen/src/handlers/propTypeHandler.ts deleted file mode 100644 index f6436583580..00000000000 --- a/packages/react-docgen/src/handlers/propTypeHandler.ts +++ /dev/null @@ -1,97 +0,0 @@ -import getPropType from '../utils/getPropType.js'; -import getPropertyName from '../utils/getPropertyName.js'; -import getMemberValuePath from '../utils/getMemberValuePath.js'; -import isReactModuleName from '../utils/isReactModuleName.js'; -import isRequiredPropType from '../utils/isRequiredPropType.js'; -import printValue from '../utils/printValue.js'; -import resolveToModule from '../utils/resolveToModule.js'; -import resolveToValue from '../utils/resolveToValue.js'; -import type Documentation from '../Documentation.js'; -import type { PropDescriptor, PropTypeDescriptor } from '../Documentation.js'; -import type { NodePath } from '@babel/traverse'; -import type { Handler } from './index.js'; -import type { ComponentNode } from '../resolver/index.js'; - -function isPropTypesExpression(path: NodePath): boolean { - const moduleName = resolveToModule(path); - - if (moduleName) { - return isReactModuleName(moduleName) || moduleName === 'ReactPropTypes'; - } - - return false; -} - -function amendPropTypes( - getDescriptor: (propName: string) => PropDescriptor, - path: NodePath, -): void { - if (!path.isObjectExpression()) { - return; - } - - path.get('properties').forEach((propertyPath) => { - if (propertyPath.isObjectProperty()) { - const propName = getPropertyName(propertyPath); - - if (!propName) return; - - const propDescriptor = getDescriptor(propName); - const valuePath = resolveToValue(propertyPath.get('value')); - const type: PropTypeDescriptor = isPropTypesExpression(valuePath) - ? getPropType(valuePath) - : { name: 'custom', raw: printValue(valuePath) }; - - if (type) { - propDescriptor.type = type; - propDescriptor.required = - type.name !== 'custom' && isRequiredPropType(valuePath); - } - } - if (propertyPath.isSpreadElement()) { - const resolvedValuePath = resolveToValue(propertyPath.get('argument')); - - if (resolvedValuePath.isObjectExpression()) { - // normal object literal - amendPropTypes(getDescriptor, resolvedValuePath); - } - } - }); -} - -function getPropTypeHandler(propName: string): Handler { - return function ( - documentation: Documentation, - componentDefinition: NodePath, - ): void { - let propTypesPath: NodePath | null = getMemberValuePath( - componentDefinition, - propName, - ); - - if (!propTypesPath) { - return; - } - propTypesPath = resolveToValue(propTypesPath); - if (!propTypesPath) { - return; - } - let getDescriptor; - - switch (propName) { - case 'childContextTypes': - getDescriptor = documentation.getChildContextDescriptor; - break; - case 'contextTypes': - getDescriptor = documentation.getContextDescriptor; - break; - default: - getDescriptor = documentation.getPropDescriptor; - } - amendPropTypes(getDescriptor.bind(documentation), propTypesPath); - }; -} - -export const propTypeHandler = getPropTypeHandler('propTypes'); -export const contextTypeHandler = getPropTypeHandler('contextTypes'); -export const childContextTypeHandler = getPropTypeHandler('childContextTypes'); diff --git a/packages/react-docgen/src/importer/fsImporter.ts b/packages/react-docgen/src/importer/fsImporter.ts deleted file mode 100644 index ceb9a46df96..00000000000 --- a/packages/react-docgen/src/importer/fsImporter.ts +++ /dev/null @@ -1,5 +0,0 @@ -import makeFsImporter from './makeFsImporter.js'; - -const defaultFsImporter = makeFsImporter(); - -export default defaultFsImporter; diff --git a/packages/react-docgen/src/importer/ignoreImporter.ts b/packages/react-docgen/src/importer/ignoreImporter.ts deleted file mode 100644 index 7220ab87c37..00000000000 --- a/packages/react-docgen/src/importer/ignoreImporter.ts +++ /dev/null @@ -1,5 +0,0 @@ -import makeIgnoreImporter from './makeIgnoreImporter.js'; - -const ignoreImporter = makeIgnoreImporter(); - -export default ignoreImporter; diff --git a/packages/react-docgen/src/importer/index.ts b/packages/react-docgen/src/importer/index.ts deleted file mode 100644 index 8bcf4e30bdf..00000000000 --- a/packages/react-docgen/src/importer/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { - ExportAllDeclaration, - ExportNamedDeclaration, - ImportDeclaration, -} from '@babel/types'; -import type FileState from '../FileState.js'; -import ignoreImporter from './ignoreImporter.js'; -import fsImporter from './fsImporter.js'; -import makeFsImporter from './makeFsImporter.js'; - -export type ImportPath = NodePath< - ExportAllDeclaration | ExportNamedDeclaration | ImportDeclaration ->; - -export type Importer = ( - path: ImportPath, - name: string, - file: FileState, -) => NodePath | null; - -export { fsImporter, ignoreImporter, makeFsImporter }; diff --git a/packages/react-docgen/src/importer/makeFsImporter.ts b/packages/react-docgen/src/importer/makeFsImporter.ts deleted file mode 100644 index bbd8b0cdf50..00000000000 --- a/packages/react-docgen/src/importer/makeFsImporter.ts +++ /dev/null @@ -1,291 +0,0 @@ -import { shallowIgnoreVisitors } from '../utils/traverse.js'; -import resolve from 'resolve'; -import { dirname, extname } from 'path'; -import fs from 'fs'; -import type { NodePath } from '@babel/traverse'; -import { visitors } from '@babel/traverse'; -import type { ExportSpecifier, ObjectProperty } from '@babel/types'; -import type { Importer, ImportPath } from './index.js'; -import type FileState from '../FileState.js'; -import { resolveObjectPatternPropertyToValue } from '../utils/index.js'; - -// These extensions are sorted by priority -// resolve() will check for files in the order these extensions are sorted -const RESOLVE_EXTENSIONS = [ - '.js', - '.ts', - '.tsx', - '.mjs', - '.cjs', - '.mts', - '.cts', - '.jsx', -]; - -function defaultLookupModule(filename: string, basedir: string): string { - const resolveOptions = { - basedir, - extensions: RESOLVE_EXTENSIONS, - // we do not need to check core modules as we cannot import them anyway - includeCoreModules: false, - }; - - try { - return resolve.sync(filename, resolveOptions); - } catch (error) { - const ext = extname(filename); - let newFilename: string; - - // if we try to import a JavaScript file it might be that we are actually pointing to - // a TypeScript file. This can happen in ES modules as TypeScript requires to import other - // TypeScript files with .js extensions - // https://www.typescriptlang.org/docs/handbook/esm-node.html#type-in-packagejson-and-new-extensions - switch (ext) { - case '.js': - case '.mjs': - case '.cjs': - newFilename = `${filename.slice(0, -2)}ts`; - break; - - case '.jsx': - newFilename = `${filename.slice(0, -3)}tsx`; - break; - default: - throw error; - } - - return resolve.sync(newFilename, { - ...resolveOptions, - // we already know that there is an extension at this point, so no need to check other extensions - extensions: [], - }); - } -} - -interface TraverseState { - readonly name: string; - readonly file: FileState; - readonly seen: Set; - resultPath?: NodePath | null; -} - -interface FsImporterCache { - parseCache: Map; - resolveCache: Map; -} - -// Factory for the resolveImports importer -// If this resolver is used in an environment where the source files change (e.g. watch) -// then the cache needs to be cleared on file changes. -export default function makeFsImporter( - lookupModule: ( - filename: string, - basedir: string, - ) => string = defaultLookupModule, - { parseCache, resolveCache }: FsImporterCache = { - parseCache: new Map(), - resolveCache: new Map(), - }, -): Importer { - function resolveImportedValue( - path: ImportPath, - name: string, - file: FileState, - seen = new Set(), - ): NodePath | null { - // Bail if no filename was provided for the current source file. - // Also never traverse into react itself. - const source = path.node.source?.value; - const { filename } = file.opts; - - if (!source || !filename || source === 'react') { - return null; - } - - // Resolve the imported module using the Node resolver - const basedir = dirname(filename); - const resolveCacheKey = `${basedir}|${source}`; - let resolvedSource = resolveCache.get(resolveCacheKey); - - // We haven't found it before, so no need to look again - if (resolvedSource === null) { - return null; - } - - // First time we try to resolve this file - if (resolvedSource === undefined) { - try { - resolvedSource = lookupModule(source, basedir); - } catch (error) { - const { code } = error as NodeJS.ErrnoException; - - if (code === 'MODULE_NOT_FOUND' || code === 'INVALID_PACKAGE_MAIN') { - resolveCache.set(resolveCacheKey, null); - - return null; - } - - throw error; - } - - resolveCache.set(resolveCacheKey, resolvedSource); - } - // Prevent recursive imports - if (seen.has(resolvedSource)) { - return null; - } - - seen.add(resolvedSource); - - let nextFile = parseCache.get(resolvedSource); - - if (!nextFile) { - // Read and parse the code - const src = fs.readFileSync(resolvedSource, 'utf8'); - - nextFile = file.parse(src, resolvedSource); - - parseCache.set(resolvedSource, nextFile); - } - - return findExportedValue(nextFile, name, seen); - } - - const explodedVisitors = visitors.explode({ - ...shallowIgnoreVisitors, - ExportNamedDeclaration: { - enter: function (path, state) { - const { file, name, seen } = state; - const declaration = path.get('declaration'); - - // export const/var ... - if (declaration.hasNode() && declaration.isVariableDeclaration()) { - for (const declPath of declaration.get('declarations')) { - const id = declPath.get('id'); - const init = declPath.get('init'); - - if (id.isIdentifier({ name }) && init.hasNode()) { - // export const/var a = - - state.resultPath = init; - - break; - } else if (id.isObjectPattern()) { - // export const/var { a } = - - state.resultPath = id.get('properties').find((prop) => { - if (prop.isObjectProperty()) { - const value = prop.get('value'); - - return value.isIdentifier({ name }); - } - // We don't handle RestElement here yet as complicated - - return false; - }); - - if (state.resultPath) { - state.resultPath = resolveObjectPatternPropertyToValue( - state.resultPath as NodePath, - ); - - break; - } - } - // ArrayPattern not handled yet - } - } else if ( - declaration.hasNode() && - declaration.has('id') && - (declaration.get('id') as NodePath).isIdentifier({ name }) - ) { - // export function/class/type/interface/enum ... - - state.resultPath = declaration; - } else if (path.has('specifiers')) { - // export { ... } or export x from ... or export * as x from ... - - for (const specifierPath of path.get('specifiers')) { - if (specifierPath.isExportNamespaceSpecifier()) { - continue; - } - const exported = specifierPath.get('exported'); - - if (exported.isIdentifier({ name })) { - // export ... from '' - if (path.has('source')) { - const local = specifierPath.isExportSpecifier() - ? specifierPath.node.local.name - : 'default'; - - state.resultPath = resolveImportedValue( - path, - local, - file, - seen, - ); - if (state.resultPath) { - break; - } - } else { - state.resultPath = ( - specifierPath as NodePath - ).get('local'); - - break; - } - } - } - } - - return state.resultPath ? path.stop() : path.skip(); - }, - }, - ExportDefaultDeclaration: { - enter: function (path, state) { - const { name } = state; - - if (name === 'default') { - state.resultPath = path.get('declaration'); - - return path.stop(); - } - - path.skip(); - }, - }, - ExportAllDeclaration: { - enter: function (path, state) { - const { name, file, seen } = state; - const resolvedPath = resolveImportedValue(path, name, file, seen); - - if (resolvedPath) { - state.resultPath = resolvedPath; - - return path.stop(); - } - - path.skip(); - }, - }, - }); - - // Traverses the program looking for an export that matches the requested name - function findExportedValue( - file: FileState, - name: string, - seen: Set, - ): NodePath | null { - const state: TraverseState = { - file, - name, - seen, - }; - - file.traverse(explodedVisitors, state); - - return state.resultPath || null; - } - - return resolveImportedValue; -} diff --git a/packages/react-docgen/src/importer/makeIgnoreImporter.ts b/packages/react-docgen/src/importer/makeIgnoreImporter.ts deleted file mode 100644 index 8981ec0ff67..00000000000 --- a/packages/react-docgen/src/importer/makeIgnoreImporter.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { Importer } from './index.js'; - -export default function makeIgnoreImporter(): Importer { - return () => null; -} diff --git a/packages/react-docgen/src/main.ts b/packages/react-docgen/src/main.ts deleted file mode 100644 index faa2bd17324..00000000000 --- a/packages/react-docgen/src/main.ts +++ /dev/null @@ -1,116 +0,0 @@ -import type DocumentationBuilder from './Documentation.js'; -import type { - BaseType, - Documentation, - ElementsType, - FunctionArgumentType, - FunctionSignatureType, - LiteralType, - MethodParameter, - MethodReturn, - ObjectSignatureType, - PropDescriptor, - PropTypeDescriptor, - SimpleType, - TSFunctionSignatureType, - TypeDescriptor, -} from './Documentation.js'; -import type FileState from './FileState.js'; -import type { Config } from './config.js'; -import { createConfig, defaultHandlers } from './config.js'; -import { ERROR_CODES } from './error.js'; -import type { Handler } from './handlers/index.js'; -import * as builtinHandlers from './handlers/index.js'; -import type { Importer } from './importer/index.js'; -import { - fsImporter, - ignoreImporter, - makeFsImporter, -} from './importer/index.js'; -import parse from './parse.js'; -import type { - Resolver, - ResolverClass, - ResolverFunction, -} from './resolver/index.js'; -import * as builtinResolvers from './resolver/index.js'; -import * as utils from './utils/index.js'; - -const builtinImporters = { - fsImporter, - ignoreImporter, -}; - -declare module '@babel/traverse' { - export interface HubInterface { - file: FileState; - parse: typeof FileState.prototype.parse; - import: typeof FileState.prototype.import; - } - - export interface Hub { - file: FileState; - parse: typeof FileState.prototype.parse; - import: typeof FileState.prototype.import; - } -} - -/** - * Parse the *src* and scan for react components based on the config - * that gets supplied. - * - * The default resolvers look for *exported* react components. - * - * By default all handlers are applied, so that all possible - * different use cases are covered. - * - * The default importer is the fs-importer that tries to resolve - * files based on the nodejs resolve algorithm. - */ -function defaultParse( - src: Buffer | string, - config: Config = {}, -): Documentation[] { - const defaultConfig = createConfig(config); - - return parse(String(src), defaultConfig); -} - -export type { NodePath } from '@babel/traverse'; -export type * as babelTypes from '@babel/types'; - -export { - builtinHandlers, - builtinImporters, - builtinResolvers, - defaultHandlers, - ERROR_CODES, - makeFsImporter, - defaultParse as parse, - utils, -}; - -export type { - BaseType, - Config, - Documentation, - DocumentationBuilder, - ElementsType, - FileState, - FunctionArgumentType, - FunctionSignatureType, - Handler, - Importer, - LiteralType, - MethodParameter, - MethodReturn, - ObjectSignatureType, - PropDescriptor, - PropTypeDescriptor, - Resolver, - ResolverClass, - ResolverFunction, - SimpleType, - TSFunctionSignatureType, - TypeDescriptor, -}; diff --git a/packages/react-docgen/src/parse.ts b/packages/react-docgen/src/parse.ts deleted file mode 100644 index cbea6b53824..00000000000 --- a/packages/react-docgen/src/parse.ts +++ /dev/null @@ -1,63 +0,0 @@ -import DocumentationBuilder from './Documentation.js'; -import type { Documentation } from './Documentation.js'; -import postProcessDocumentation from './utils/postProcessDocumentation.js'; -import babelParse from './babelParser.js'; -import type { NodePath } from '@babel/traverse'; -import type { Handler } from './handlers/index.js'; -import type { ComponentNode } from './resolver/index.js'; -import FileState from './FileState.js'; -import type { InternalConfig } from './config.js'; -import { ERROR_CODES, ReactDocgenError } from './error.js'; -import runResolver from './resolver/utils/runResolver.js'; - -function executeHandlers( - handlers: Handler[], - componentDefinitions: Array>, -): Documentation[] { - return componentDefinitions.map((componentDefinition): Documentation => { - const documentation = new DocumentationBuilder(); - - handlers.forEach((handler) => handler(documentation, componentDefinition)); - - return postProcessDocumentation(documentation.build()); - }); -} - -/** - * Takes JavaScript source code and returns an object with the information - * extract from it. - * - * `resolver` is a strategy to find the AST node(s) of the component - * definition(s) inside `src`. - * It is a function that gets passed the program AST node of - * the source as first argument, and a reference to the parser as second argument. - * - * This allows you define your own strategy for finding component definitions. - * - * `handlers` is an array of functions which are passed a reference to the - * component definitions (extracted by `resolver`) so that they can extract - * information from it. They get also passed a reference to a `Documentation` - * object to attach the information to. A reference to the parser is parsed as the - * last argument. - */ -export default function parse( - code: string, - config: InternalConfig, -): Documentation[] { - const { babelOptions, handlers, importer, resolver } = config; - const ast = babelParse(code, babelOptions); - - const fileState = new FileState(babelOptions, { - ast, - code, - importer, - }); - - const componentDefinitions = runResolver(resolver, fileState); - - if (componentDefinitions.length === 0) { - throw new ReactDocgenError(ERROR_CODES.MISSING_DEFINITION); - } - - return executeHandlers(handlers, componentDefinitions); -} diff --git a/packages/react-docgen/src/resolver/ChainResolver.ts b/packages/react-docgen/src/resolver/ChainResolver.ts deleted file mode 100644 index cf156cdece0..00000000000 --- a/packages/react-docgen/src/resolver/ChainResolver.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type FileState from '../FileState.js'; -import type { ComponentNodePath, Resolver, ResolverClass } from './index.js'; -import runResolver from './utils/runResolver.js'; - -enum ChainingLogic { - ALL, - FIRST_FOUND, -} - -interface ChainResolverOptions { - chainingLogic?: ChainingLogic; -} - -export default class ChainResolver implements ResolverClass { - resolvers: Resolver[]; - options: ChainResolverOptions; - - static Logic = ChainingLogic; - - constructor(resolvers: Resolver[], options: ChainResolverOptions) { - this.resolvers = resolvers; - this.options = options; - } - - private resolveFirstOnly(file: FileState): ComponentNodePath[] { - for (const resolver of this.resolvers) { - const components = runResolver(resolver, file); - - if (components.length > 0) { - return components; - } - } - - return []; - } - - private resolveAll(file: FileState): ComponentNodePath[] { - const allComponents = new Set(); - - for (const resolver of this.resolvers) { - const components = runResolver(resolver, file); - - components.forEach((component) => { - allComponents.add(component); - }); - } - - return Array.from(allComponents); - } - - resolve(file: FileState): ComponentNodePath[] { - if (this.options.chainingLogic === ChainingLogic.FIRST_FOUND) { - return this.resolveFirstOnly(file); - } - - return this.resolveAll(file); - } -} diff --git a/packages/react-docgen/src/resolver/FindAllDefinitionsResolver.ts b/packages/react-docgen/src/resolver/FindAllDefinitionsResolver.ts deleted file mode 100644 index 5f7a4ed7666..00000000000 --- a/packages/react-docgen/src/resolver/FindAllDefinitionsResolver.ts +++ /dev/null @@ -1,100 +0,0 @@ -import isReactComponentClass from '../utils/isReactComponentClass.js'; -import isReactCreateClassCall from '../utils/isReactCreateClassCall.js'; -import isReactForwardRefCall from '../utils/isReactForwardRefCall.js'; -import isStatelessComponent from '../utils/isStatelessComponent.js'; -import normalizeClassDefinition from '../utils/normalizeClassDefinition.js'; -import resolveToValue from '../utils/resolveToValue.js'; -import type { NodePath } from '@babel/traverse'; -import { visitors } from '@babel/traverse'; -import type FileState from '../FileState.js'; -import type { ComponentNodePath, ResolverClass } from './index.js'; -import type { - ArrowFunctionExpression, - FunctionDeclaration, - FunctionExpression, - ObjectMethod, -} from '@babel/types'; - -interface TraverseState { - foundDefinitions: Set; -} - -function classVisitor(path: NodePath, state: TraverseState): void { - if (isReactComponentClass(path)) { - normalizeClassDefinition(path); - state.foundDefinitions.add(path); - } - - path.skip(); -} - -function statelessVisitor( - path: NodePath< - | ArrowFunctionExpression - | FunctionDeclaration - | FunctionExpression - | ObjectMethod - >, - state: TraverseState, -): void { - if (isStatelessComponent(path)) { - state.foundDefinitions.add(path); - } - - path.skip(); -} - -const explodedVisitors = visitors.explode({ - FunctionDeclaration: { enter: statelessVisitor }, - FunctionExpression: { enter: statelessVisitor }, - ObjectMethod: { enter: statelessVisitor }, - ArrowFunctionExpression: { enter: statelessVisitor }, - ClassExpression: { enter: classVisitor }, - ClassDeclaration: { enter: classVisitor }, - CallExpression: { - enter: function (path, state): void { - const argument = path.get('arguments')[0]; - - if (!argument) { - return; - } - - if (isReactForwardRefCall(path)) { - // If the the inner function was previously identified as a component - // replace it with the parent node - const inner = resolveToValue(argument) as ComponentNodePath; - - state.foundDefinitions.delete(inner); - state.foundDefinitions.add(path); - - // Do not traverse into arguments - return path.skip(); - } else if (isReactCreateClassCall(path)) { - const resolvedPath = resolveToValue(argument); - - if (resolvedPath.isObjectExpression()) { - state.foundDefinitions.add(resolvedPath); - } - - // Do not traverse into arguments - return path.skip(); - } - }, - }, -}); - -/** - * Given an AST, this function tries to find all object expressions that are - * passed to `React.createClass` calls, by resolving all references properly. - */ -export default class FindAllDefinitionsResolver implements ResolverClass { - resolve(file: FileState): ComponentNodePath[] { - const state: TraverseState = { - foundDefinitions: new Set(), - }; - - file.traverse(explodedVisitors, state); - - return Array.from(state.foundDefinitions); - } -} diff --git a/packages/react-docgen/src/resolver/FindAnnotatedDefinitionsResolver.ts b/packages/react-docgen/src/resolver/FindAnnotatedDefinitionsResolver.ts deleted file mode 100644 index 39287f095d4..00000000000 --- a/packages/react-docgen/src/resolver/FindAnnotatedDefinitionsResolver.ts +++ /dev/null @@ -1,115 +0,0 @@ -import normalizeClassDefinition from '../utils/normalizeClassDefinition.js'; -import type { NodePath } from '@babel/traverse'; -import { visitors } from '@babel/traverse'; -import type FileState from '../FileState.js'; -import type { ComponentNodePath, ResolverClass } from './index.js'; -import type { - ArrowFunctionExpression, - ClassDeclaration, - ClassExpression, - FunctionDeclaration, - FunctionExpression, - ObjectMethod, -} from '@babel/types'; - -interface TraverseState { - foundDefinitions: Set; - annotation: string; -} - -function isAnnotated(path: NodePath, annotation: string): boolean { - let inspectPath: NodePath | null = path; - - do { - const leadingComments = inspectPath.node.leadingComments; - - // If an export doesn't have leading comments, we can simply continue - if (leadingComments && leadingComments.length > 0) { - // Search for the annotation in any comment. - const hasAnnotation = leadingComments.some(({ value }) => - value.includes(annotation), - ); - - // if we found an annotation return true - if (hasAnnotation) { - return true; - } - } - - // return false if the container of the current path is an array - // as we do not want to traverse up through this kind of nodes, like ArrayExpressions for example - // The only exception is variable declarations - if ( - Array.isArray(inspectPath.container) && - !inspectPath.isVariableDeclarator() && - !inspectPath.parentPath?.isCallExpression() - ) { - return false; - } - } while ((inspectPath = inspectPath.parentPath)); - - return false; -} - -function classVisitor( - path: NodePath, - state: TraverseState, -): void { - if (isAnnotated(path, state.annotation)) { - normalizeClassDefinition(path); - state.foundDefinitions.add(path); - } -} - -function statelessVisitor( - path: NodePath< - | ArrowFunctionExpression - | FunctionDeclaration - | FunctionExpression - | ObjectMethod - >, - state: TraverseState, -): void { - if (isAnnotated(path, state.annotation)) { - state.foundDefinitions.add(path); - } -} - -const explodedVisitors = visitors.explode({ - ArrowFunctionExpression: { enter: statelessVisitor }, - FunctionDeclaration: { enter: statelessVisitor }, - FunctionExpression: { enter: statelessVisitor }, - ObjectMethod: { enter: statelessVisitor }, - - ClassDeclaration: { enter: classVisitor }, - ClassExpression: { enter: classVisitor }, -}); - -interface FindAnnotatedDefinitionsResolverOptions { - annotation?: string; -} - -/** - * Given an AST, this function tries to find all react components which - * are annotated with an annotation - */ -export default class FindAnnotatedDefinitionsResolver implements ResolverClass { - annotation: string; - - constructor({ - annotation = '@component', - }: FindAnnotatedDefinitionsResolverOptions = {}) { - this.annotation = annotation; - } - - resolve(file: FileState): ComponentNodePath[] { - const state: TraverseState = { - foundDefinitions: new Set(), - annotation: this.annotation, - }; - - file.traverse(explodedVisitors, state); - - return Array.from(state.foundDefinitions); - } -} diff --git a/packages/react-docgen/src/resolver/FindExportedDefinitionsResolver.ts b/packages/react-docgen/src/resolver/FindExportedDefinitionsResolver.ts deleted file mode 100644 index 1c2eba0c035..00000000000 --- a/packages/react-docgen/src/resolver/FindExportedDefinitionsResolver.ts +++ /dev/null @@ -1,114 +0,0 @@ -import isExportsOrModuleAssignment from '../utils/isExportsOrModuleAssignment.js'; -import resolveExportDeclaration from '../utils/resolveExportDeclaration.js'; -import resolveToValue from '../utils/resolveToValue.js'; -import type { NodePath } from '@babel/traverse'; -import { visitors } from '@babel/traverse'; -import { shallowIgnoreVisitors } from '../utils/traverse.js'; -import type { - AssignmentExpression, - ExportDefaultDeclaration, - ExportNamedDeclaration, -} from '@babel/types'; -import type FileState from '../FileState.js'; -import type { ComponentNodePath, ResolverClass } from './index.js'; -import findComponentDefinition from '../utils/findComponentDefinition.js'; -import { ERROR_CODES, ReactDocgenError } from '../error.js'; - -interface TraverseState { - foundDefinitions: Set; - limit: number; -} - -function exportDeclaration( - path: NodePath, - state: TraverseState, -): void { - resolveExportDeclaration(path).forEach((exportedPath) => { - const definition = findComponentDefinition(exportedPath); - - if (definition) { - if (state.limit > 0 && state.foundDefinitions.size > 0) { - // If a file exports multiple components, ... complain! - throw new ReactDocgenError(ERROR_CODES.MULTIPLE_DEFINITIONS); - } - - state.foundDefinitions.add(definition); - } - }); - - return path.skip(); -} - -function assignmentExpressionVisitor( - path: NodePath, - state: TraverseState, -): void { - // Ignore anything that is not `exports.X = ...;` or - // `module.exports = ...;` - if (!isExportsOrModuleAssignment(path)) { - return path.skip(); - } - // Resolve the value of the right hand side. It should resolve to a call - // expression, something like React.createClass - const resolvedPath = resolveToValue(path.get('right')); - const definition = findComponentDefinition(resolvedPath); - - if (definition) { - if (state.limit > 0 && state.foundDefinitions.size > 0) { - // If a file exports multiple components, ... complain! - throw new ReactDocgenError(ERROR_CODES.MULTIPLE_DEFINITIONS); - } - - state.foundDefinitions.add(definition); - } - - return path.skip(); -} - -const explodedVisitors = visitors.explode({ - ...shallowIgnoreVisitors, - - ExportNamedDeclaration: { enter: exportDeclaration }, - ExportDefaultDeclaration: { enter: exportDeclaration }, - AssignmentExpression: { enter: assignmentExpressionVisitor }, -}); - -interface FindExportedDefinitionsResolverOptions { - limit?: number; -} - -/** - * Given an AST, this function tries to find the exported component definitions. - * - * The component definitions are either the ObjectExpression passed to - * `React.createClass` or a `class` definition extending `React.Component` or - * having a `render()` method. - * - * If a definition is part of the following statements, it is considered to be - * exported: - * - * modules.exports = Definition; - * exports.foo = Definition; - * export default Definition; - * export var Definition = ...; - * - * limit can be used to limit the components to be found. When the limit is reached an error will be thrown - */ -export default class FindExportedDefinitionsResolver implements ResolverClass { - limit: number; - - constructor({ limit = 0 }: FindExportedDefinitionsResolverOptions = {}) { - this.limit = limit; - } - - resolve(file: FileState): ComponentNodePath[] { - const state: TraverseState = { - foundDefinitions: new Set(), - limit: this.limit, - }; - - file.traverse(explodedVisitors, state); - - return Array.from(state.foundDefinitions); - } -} diff --git a/packages/react-docgen/src/resolver/__tests__/ChainResolver-test.ts b/packages/react-docgen/src/resolver/__tests__/ChainResolver-test.ts deleted file mode 100644 index 731c04d9eff..00000000000 --- a/packages/react-docgen/src/resolver/__tests__/ChainResolver-test.ts +++ /dev/null @@ -1,109 +0,0 @@ -import ChainResolver from '../ChainResolver.js'; -import { describe, expect, test, vi } from 'vitest'; -import FileStateMock from '../../__mocks__/FileState'; -import { blockStatement, functionExpression } from '@babel/types'; - -describe('ChainResolver', () => { - const fileStateMock = new FileStateMock(); - const component1 = functionExpression(null, [], blockStatement([])); - const component2 = functionExpression(null, [], blockStatement([])); - - test('can be used with only one resolver', () => { - const resolver = vi.fn().mockReturnValue([]); - const chainResolver = new ChainResolver([resolver], { - chainingLogic: ChainResolver.Logic.ALL, - }); - - chainResolver.resolve(fileStateMock); - - expect(resolver).toHaveBeenCalledOnce(); - expect(resolver).toHaveBeenCalledWith(fileStateMock); - }); - - test('can be used with multiple resolvers', () => { - const resolver1 = vi.fn().mockReturnValue([]); - const resolver2 = vi.fn().mockReturnValue([]); - const chainResolver = new ChainResolver([resolver1, resolver2], { - chainingLogic: ChainResolver.Logic.ALL, - }); - - chainResolver.resolve(fileStateMock); - - expect(resolver1).toHaveBeenCalledOnce(); - expect(resolver1).toHaveBeenCalledWith(fileStateMock); - expect(resolver2).toHaveBeenCalledOnce(); - expect(resolver2).toHaveBeenCalledWith(fileStateMock); - }); - - test('returns all components from all resolvers with ALL logic', () => { - const resolver1 = vi.fn().mockReturnValue([component1]); - const resolver2 = vi.fn().mockReturnValue([component2]); - const chainResolver = new ChainResolver([resolver1, resolver2], { - chainingLogic: ChainResolver.Logic.ALL, - }); - - const result = chainResolver.resolve(fileStateMock); - - expect(result).toEqual([component1, component2]); - }); - - test('returns no duplicates with ALL logic', () => { - const resolver1 = vi.fn().mockReturnValue([component1]); - const resolver2 = vi.fn().mockReturnValue([component1, component2]); - const chainResolver = new ChainResolver([resolver1, resolver2], { - chainingLogic: ChainResolver.Logic.ALL, - }); - - const result = chainResolver.resolve(fileStateMock); - - expect(result).toEqual([component1, component2]); - }); - - test('returns first found components with FIRST_FOUND logic', () => { - const resolver1 = vi.fn().mockReturnValue([component1]); - const resolver2 = vi.fn().mockReturnValue([component2]); - const chainResolver = new ChainResolver([resolver1, resolver2], { - chainingLogic: ChainResolver.Logic.FIRST_FOUND, - }); - - const result = chainResolver.resolve(fileStateMock); - - expect(result).toEqual([component1]); - }); - - test('returns empty array if no components found with ALL logic', () => { - const resolver1 = vi.fn().mockReturnValue([]); - const resolver2 = vi.fn().mockReturnValue([]); - const chainResolver = new ChainResolver([resolver1, resolver2], { - chainingLogic: ChainResolver.Logic.ALL, - }); - - const result = chainResolver.resolve(fileStateMock); - - expect(result).toEqual([]); - }); - - test('returns empty array if no components found with FIRST_FOUND logic', () => { - const resolver1 = vi.fn().mockReturnValue([]); - const resolver2 = vi.fn().mockReturnValue([]); - const chainResolver = new ChainResolver([resolver1, resolver2], { - chainingLogic: ChainResolver.Logic.FIRST_FOUND, - }); - - const result = chainResolver.resolve(fileStateMock); - - expect(result).toEqual([]); - }); - - test('throws if resolver throws', () => { - const error = new Error('test'); - const resolver = vi.fn().mockImplementation(() => { - throw error; - }); - const chainResolver = new ChainResolver([resolver], { - chainingLogic: ChainResolver.Logic.ALL, - }); - - expect(() => chainResolver.resolve(fileStateMock)).toThrowError(error); - }); -}); diff --git a/packages/react-docgen/src/resolver/__tests__/FindAllDefinitionsResolver-test.ts b/packages/react-docgen/src/resolver/__tests__/FindAllDefinitionsResolver-test.ts deleted file mode 100644 index 62b48a9e539..00000000000 --- a/packages/react-docgen/src/resolver/__tests__/FindAllDefinitionsResolver-test.ts +++ /dev/null @@ -1,361 +0,0 @@ -import { NodePath } from '@babel/traverse'; -import { parse, makeMockImporter, noopImporter } from '../../../tests/utils'; -import FindAllDefinitionsResolver from '../FindAllDefinitionsResolver.js'; -import { describe, expect, test } from 'vitest'; - -describe('FindAllDefinitionsResolver', () => { - const resolver = new FindAllDefinitionsResolver(); - - function findComponentsInSource( - source: string, - importer = noopImporter, - ): NodePath[] { - return resolver.resolve(parse(source, {}, importer, true)); - } - - const mockImporter = makeMockImporter({ - obj: (stmtLast) => stmtLast(`export default {};`).get('declaration'), - - reactComponent: (stmtLast) => - stmtLast(` - import React from 'react'; - export default React.Component; - `).get('declaration'), - - reactPureComponent: (stmtLast) => - stmtLast(` - import React from 'react'; - export default React.PureComponent; - `).get('declaration'), - - jsxDiv: (stmtLast) => - stmtLast(`export default
;`).get('declaration'), - - createElement: (stmtLast) => - stmtLast(` - import React from 'react'; - export default React.createElement('div', null); - `).get('declaration'), - - arrowJsx: (stmtLast) => - stmtLast(`export default (props) =>
{props.children}
;`).get( - 'declaration', - ), - - coloredView: (stmtLast) => - stmtLast(`export default function ColoredView(props, ref) { - return
- };`).get('declaration'), - }); - - describe('React.createClass', () => { - test('finds React.createClass', () => { - const source = ` - var React = require("React"); - var Component = React.createClass({}); - module.exports = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(1); - expect(result[0] instanceof NodePath).toBe(true); - expect(result[0].node.type).toBe('ObjectExpression'); - }); - - test('resolves imported values inside React.createClass', () => { - const source = ` - import obj from 'obj'; - var React = require("React"); - var Component = React.createClass(obj); - module.exports = Component; - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(1); - expect(result[0] instanceof NodePath).toBe(true); - expect(result[0].node.type).toBe('ObjectExpression'); - }); - - test('finds React.createClass, independent of the var name', () => { - const source = ` - var R = require("React"); - var Component = R.createClass({}); - module.exports = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(1); - }); - - test('does not process X.createClass of other modules', () => { - const source = ` - var R = require("NoReact"); - var Component = R.createClass({}); - module.exports = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(0); - }); - - test('finds assignments to exports', () => { - const source = ` - var R = require("React"); - var Component = R.createClass({}); - exports.foo = 42; - exports.Component = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(1); - }); - - test('accepts multiple definitions', () => { - let source = ` - var R = require("React"); - var ComponentA = R.createClass({}); - var ComponentB = R.createClass({}); - exports.ComponentB = ComponentB; - `; - - let result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(2); - - source = ` - var R = require("React"); - var ComponentA = R.createClass({}); - var ComponentB = R.createClass({}); - module.exports = ComponentB; - `; - - result = findComponentsInSource(source); - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(2); - }); - }); - - describe('class definitions', () => { - test('finds component classes', () => { - const source = ` - import React from 'React'; - class ComponentA extends React.Component {} - class ComponentB extends Foo { render() {} } - var ComponentC = class extends React.PureComponent {} - var ComponentD = class extends Bar { render() {} } - class NotAComponent {} - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(4); - }); - - test('resolves extends React.Component/React.PureComponent from import', () => { - const source = ` - import Component from 'reactComponent'; - import PureComponent from 'reactPureComponent'; - class ComponentA extends Component {} - var ComponentC = class extends PureComponent {} - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(2); - }); - - test('finds React.Component, independent of the var name', () => { - const source = ` - import R from 'React'; - class Component extends R.Component {}; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(1); - }); - - test('does not process X.Component of other modules', () => { - const source = ` - import R from 'FakeReact'; - class Component extends R.Component {}; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(0); - }); - }); - - describe('stateless components', () => { - test('finds stateless components', () => { - const source = ` - import React from 'React'; - let ComponentA = () =>
; - function ComponentB () { return React.createElement('div', null); } - const ComponentC = function(props) { return
{props.children}
; }; - var Obj = { - component() { if (true) { return
; } } - }; - const ComponentD = function(props) { - var result =
{props.children}
; - return result; - }; - const ComponentE = function(props) { - var result = () =>
{props.children}
; - return result(); - }; - const ComponentF = function(props) { - var helpers = { - comp() { return
{props.children}
; } - }; - return helpers.comp(); - }; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(7); - }); - - test('resolve renders from imports', () => { - const source = ` - import jsxDiv from 'jsxDiv'; - import createElement from 'createElement'; - import arrowJsx from 'arrowJsx'; - let ComponentA = () => jsxDiv; - function ComponentB () { return createElement; } - const ComponentC = function(props) { return arrowJsx(props); }; - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(3); - }); - - test('finds React.createElement, independent of the var name', () => { - const source = ` - import AlphaBetters from 'react'; - function ComponentA () { return AlphaBetters.createElement('div', null); } - function ComponentB () { return 7; } - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(1); - }); - - test('does not process X.createElement of other modules', () => { - const source = ` - import R from 'FakeReact'; - const ComponentA = () => R.createElement('div', null); - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(0); - }); - }); - - describe('forwardRef components', () => { - test('finds forwardRef components', () => { - const source = ` - import React from 'react'; - import PropTypes from 'prop-types'; - import extendStyles from 'enhancers/extendStyles'; - - const ColoredView = React.forwardRef((props, ref) => ( -
- )); - - extendStyles(ColoredView); - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(1); - expect(result[0].node.type).toEqual('CallExpression'); - }); - - test('finds none inline forwardRef components', () => { - const source = ` - import React from 'react'; - import PropTypes from 'prop-types'; - import extendStyles from 'enhancers/extendStyles'; - - function ColoredView(props, ref) { - return
- } - - const ForwardedColoredView = React.forwardRef(ColoredView); - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(1); - expect(result[0].node.type).toEqual('CallExpression'); - }); - - test('resolves imported component wrapped with forwardRef', () => { - const source = ` - import React from 'react'; - import ColoredView from 'coloredView'; - const ForwardedColoredView = React.forwardRef(ColoredView); - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(1); - expect(result[0].node.type).toEqual('CallExpression'); - }); - }); - - describe('regressions', () => { - test('finds component wrapped in HOC', () => { - const source = ` - /** - * @flow - */ - import * as React from 'react'; - - type Props = $ReadOnly<{| - tabs: $ReadOnlyArray, - |}>; - - const TetraAdminTabs = React.memo((props: Props) => ( -
- )); - - export default TetraAdminTabs; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(1); - expect(result[0].node.type).toEqual('ArrowFunctionExpression'); - }); - }); -}); diff --git a/packages/react-docgen/src/resolver/__tests__/FindAnnotatedDefinitionsResolver-test.ts b/packages/react-docgen/src/resolver/__tests__/FindAnnotatedDefinitionsResolver-test.ts deleted file mode 100644 index 445c33552a2..00000000000 --- a/packages/react-docgen/src/resolver/__tests__/FindAnnotatedDefinitionsResolver-test.ts +++ /dev/null @@ -1,235 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import { parse, noopImporter } from '../../../tests/utils'; -import FindAnnotatedDefinitionsResolver from '../FindAnnotatedDefinitionsResolver.js'; -import { describe, expect, test } from 'vitest'; - -describe('FindAnnotatedDefinitionsResolver', () => { - const resolver = new FindAnnotatedDefinitionsResolver(); - - function findComponentsInSource( - source: string, - importer = noopImporter, - ): NodePath[] { - return resolver.resolve(parse(source, {}, importer, true)); - } - - describe('class definitions', () => { - test('finds ClassDeclaration with line comment', () => { - const source = ` - // @component - class Component {} - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('finds ClassDeclaration with line comment and empty line', () => { - const source = ` - // @component - - class Component {} - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('finds ClassDeclaration with block comment', () => { - const source = ` - /* @component */ - class Component {} - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('finds ClassDeclaration with block comment and empty line', () => { - const source = ` - /* @component */ - - class Component {} - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('finds ClassExpression', () => { - const source = ` - // @component - const Component = class {} - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('finds ClassExpression with assignment', () => { - const source = ` - let Component; - // @component - Component = class {} - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('finds nothing when not annotated', () => { - const source = ` - class ComponentA {} - const ComponentB = class {} - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(0); - }); - }); - - describe('stateless components', () => { - test('finds ArrowFunctionExpression', () => { - const source = ` - // @component - const Component = () => {}; - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('finds FunctionDeclaration', () => { - const source = ` - // @component - function Component() {} - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('finds FunctionExpression', () => { - const source = ` - // @component - const Component = function() {}; - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('finds ObjectMethod', () => { - const source = ` - const obj = { - // @component - component() {} - }; - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('finds ObjectProperty', () => { - const source = ` - const obj = { - // @component - component: function() {} - }; - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('finds nothing when not annotated', () => { - const source = ` - const ComponentA = () => {}; - function ComponentB() {} - const ComponentC = function() {}; - const obj = { component() {} }; - const obj2 = { component: function() {} }; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(0); - }); - }); - - test('finds component wrapped in HOC', () => { - const source = ` - // @component - const Component = React.memo(() => {}); - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('finds named exported component', () => { - const source = ` - // @component - export const Component = () => {}; - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('finds default exported component', () => { - const source = ` - // @component - export default () => {}; - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('finds component wrapped in two HOCs', () => { - const source = ` - // @component - const Component = React.memo(otherHOC(() => {})); - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('finds component wrapped in function', () => { - const source = ` - function X () { - // @component - const subcomponent = class {} - } - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); - - test('does not traverse up ArrayExpressions', () => { - const source = ` - // @component - const arr = [ - function() {}, - function() {} - ] - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(0); - }); - - test('does not traverse up function parameters', () => { - const source = ` - // @component - function x(component = () => {}) {} - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result.length).toBe(1); - expect(result[0].type).not.toBe('ArrowFunctionExpression'); - }); - - test('finds function parameter with annotation', () => { - const source = ` - function x(component = /* @component */() => {}) {} - `; - - expect(findComponentsInSource(source)).toMatchSnapshot(); - }); -}); diff --git a/packages/react-docgen/src/resolver/__tests__/FindExportedDefinitionsResolver-test.ts b/packages/react-docgen/src/resolver/__tests__/FindExportedDefinitionsResolver-test.ts deleted file mode 100644 index 2297923e495..00000000000 --- a/packages/react-docgen/src/resolver/__tests__/FindExportedDefinitionsResolver-test.ts +++ /dev/null @@ -1,2444 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import { parse, noopImporter, makeMockImporter } from '../../../tests/utils'; -import FindExportedDefinitionsResolver from '../FindExportedDefinitionsResolver.js'; -import { describe, expect, test } from 'vitest'; - -describe('FindExportedDefinitionsResolver', () => { - describe('no limit', () => { - const resolver = new FindExportedDefinitionsResolver(); - - function findComponentsInSource( - source: string, - importer = noopImporter, - ): NodePath[] { - return resolver.resolve(parse(source, {}, importer, true)); - } - - const mockImporter = makeMockImporter({ - createClass: (stmtLast) => - stmtLast(` - import React from 'react' - export default React.createClass({}) - `).get('declaration'), - - classDec: (stmtLast) => - stmtLast(` - import React from 'react' - export default class Component extends React.Component {} - `).get('declaration'), - - classExpr: (stmtLast) => - stmtLast(` - import React from 'react' - var Component = class extends React.Component {} - export default Component - `).get('declaration'), - - statelessJsx: (stmtLast) => - stmtLast(` - export default () =>
- `).get('declaration'), - - statelessCreateElement: (stmtLast) => - stmtLast(` - import React from 'react' - export default () => React.createElement('div', {}) - `).get('declaration'), - - forwardRef: (stmtLast) => - stmtLast(` - import React from 'react' - export default React.forwardRef((props, ref) => ( -
- )) - `).get('declaration'), - }); - - describe('CommonJS module exports', () => { - describe('React.createClass', () => { - test('finds React.createClass', () => { - const result = findComponentsInSource(` - var React = require("React"); - var Component = React.createClass({}); - module.exports = Component; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds React.createClass, independent of the var name', () => { - const result = findComponentsInSource(` - var R = require("React"); - var Component = R.createClass({}); - module.exports = Component; - `); - - expect(result).toMatchSnapshot(); - }); - - test('does not process X.createClass of other modules', () => { - const result = findComponentsInSource(` - var R = require("NoReact"); - var Component = R.createClass({}); - module.exports = Component; - `); - - expect(result).toMatchSnapshot(); - }); - - test('resolves an imported variable to React.createClass', () => { - const result = findComponentsInSource( - ` - import Component from 'createClass'; - module.exports = Component; - `, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - - describe('class definitions', () => { - test('finds class declarations', () => { - const result = findComponentsInSource(` - var React = require("React"); - class Component extends React.Component {} - module.exports = Component; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds class expression', () => { - const result = findComponentsInSource(` - var React = require("React"); - var Component = class extends React.Component {} - module.exports = Component; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds class definition, independent of the var name', () => { - const result = findComponentsInSource(` - var R = require("React"); - class Component extends R.Component {} - module.exports = Component; - `); - - expect(result).toMatchSnapshot(); - }); - - test('resolves an imported variable to class declaration', () => { - const result = findComponentsInSource( - ` - import Component from 'classDec'; - module.exports = Component; - `, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - - test('resolves an imported variable to class expression', () => { - const result = findComponentsInSource( - ` - import Component from 'classExpr'; - module.exports = Component; - `, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - - describe('stateless components', () => { - test('finds stateless component with JSX', () => { - const result = findComponentsInSource(` - var React = require("React"); - var Component = () =>
; - module.exports = Component; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds stateless components with React.createElement, independent of the var name', () => { - const result = findComponentsInSource(` - var R = require("React"); - var Component = () => R.createElement('div', {}); - module.exports = Component; - `); - - expect(result).toMatchSnapshot(); - }); - - test('does not process X.createElement of other modules', () => { - const result = findComponentsInSource(` - var R = require("NoReact"); - var Component = () => R.createElement({}); - module.exports = Component; - `); - - expect(result).toMatchSnapshot(); - }); - - test('resolves an imported stateless component with JSX', () => { - const result = findComponentsInSource( - ` - import Component from 'statelessJsx'; - module.exports = Component; - `, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - - test('resolves an imported stateless component with React.createElement', () => { - const result = findComponentsInSource( - ` - import Component from 'statelessCreateElement'; - module.exports = Component; - `, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - - describe('forwardRef components', () => { - test('finds forwardRef components', () => { - const result = findComponentsInSource(` - import React from 'react'; - import PropTypes from 'prop-types'; - import extendStyles from 'enhancers/extendStyles'; - - const ColoredView = React.forwardRef((props, ref) => ( -
- )); - - module.exports = extendStyles(ColoredView); - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds none inline forwardRef components', () => { - const result = findComponentsInSource(` - import React from 'react'; - import PropTypes from 'prop-types'; - import extendStyles from 'enhancers/extendStyles'; - - function ColoredView(props, ref) { - return
- } - - const ForwardedColoredView = React.forwardRef(ColoredView); - - module.exports = ForwardedColoredView - `); - - expect(result).toMatchSnapshot(); - }); - - test('resolves an imported forwardRef component', () => { - const result = findComponentsInSource( - ` - import Component from 'forwardRef'; - module.exports = Component; - `, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - - describe('module.exports = ; / exports.foo = ;', () => { - describe('React.createClass', () => { - test('finds assignments to exports', () => { - const result = findComponentsInSource(` - var R = require("React"); - var Component = R.createClass({}); - exports.foo = 42; - exports.Component = Component; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple exported components', () => { - const result = findComponentsInSource(` - var R = require("React"); - var ComponentA = R.createClass({}); - var ComponentB = R.createClass({}); - exports.ComponentA = ComponentA; - exports.ComponentB = ComponentB; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple exported components with hocs', () => { - const result = findComponentsInSource(` - var R = require("React"); - var ComponentA = R.createClass({}); - var ComponentB = R.createClass({}); - exports.ComponentA = hoc(ComponentA); - exports.ComponentB = hoc(ComponentB); - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds only exported components on export', () => { - const result = findComponentsInSource(` - var R = require("React"); - var ComponentA = R.createClass({}); - var ComponentB = R.createClass({}); - exports.ComponentB = ComponentB; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds only exported components', () => { - const result = findComponentsInSource(` - var R = require("React"); - var ComponentA = R.createClass({}); - var ComponentB = R.createClass({}); - module.exports = ComponentB; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds exported components only once', () => { - const result = findComponentsInSource(` - var R = require("React"); - var ComponentA = R.createClass({}); - exports.ComponentA = ComponentA; - exports.ComponentB = ComponentA; - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components', () => { - const result = findComponentsInSource( - ` - import Component from 'createClass'; - exports.ComponentA = Component; - exports.ComponentB = Component; - `, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - - describe('class definition', () => { - test('finds assignments to exports', () => { - const result = findComponentsInSource(` - var R = require("React"); - class Component extends R.Component {} - exports.foo = 42; - exports.Component = Component; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple exported components', () => { - const result = findComponentsInSource(` - var R = require("React"); - class ComponentA extends R.Component {} - class ComponentB extends R.Component {} - exports.ComponentA = ComponentA; - exports.ComponentB = ComponentB; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds only exported components on export', () => { - const result = findComponentsInSource(` - var R = require("React"); - class ComponentA extends R.Component {} - class ComponentB extends R.Component {} - exports.ComponentB = ComponentB; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds only exported components', () => { - const result = findComponentsInSource(` - var R = require("React"); - class ComponentA extends R.Component {} - class ComponentB extends R.Component {} - module.exports = ComponentB; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds exported components only once', () => { - const result = findComponentsInSource(` - var R = require("React"); - class ComponentA extends R.Component {} - exports.ComponentA = ComponentA; - exports.ComponentB = ComponentA; - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components', () => { - const result = findComponentsInSource( - ` - import Component from 'classDec'; - exports.ComponentA = Component; - exports.ComponentB = Component; - `, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - }); - }); - - describe('ES6 export declarations', () => { - describe('export default ;', () => { - describe('React.createClass', () => { - test('finds reassigned default export', () => { - const result = findComponentsInSource(` - var React = require("React"); - var Component = React.createClass({}); - export default Component - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds default export', () => { - const result = findComponentsInSource(` - var React = require("React"); - export default React.createClass({}); - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple exported components with export var', () => { - const result = findComponentsInSource(` - import React, { createElement } from "React" - export var Component = React.createClass({}); - export default React.createClass({}); - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple exported components with named export', () => { - const result = findComponentsInSource(` - import React, { createElement } from "React" - var Component = React.createClass({}) - export {Component}; - export default React.createClass({}); - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds only exported components', () => { - const result = findComponentsInSource(` - import React, { createElement } from "React" - var Component = React.createClass({}) - export default React.createClass({}); - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components', () => { - const result = findComponentsInSource( - `import Component from 'createClass'; - export default Component;`, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - - describe('class definition', () => { - test('finds default export', () => { - const result = findComponentsInSource(` - import React from 'React'; - class Component extends React.Component {} - export default Component; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds default export inline', () => { - const result = findComponentsInSource(` - import React from 'React'; - export default class Component extends React.Component {}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple exported components with export var', () => { - const result = findComponentsInSource(` - import React from 'React'; - export var Component = class extends React.Component {}; - export default class ComponentB extends React.Component{}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple exported components with named export', () => { - const result = findComponentsInSource(` - import React from 'React'; - var Component = class extends React.Component {}; - export {Component}; - export default class ComponentB extends React.Component{}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds only exported components', () => { - const result = findComponentsInSource(` - import React from 'React'; - var Component = class extends React.Component {}; - export default class ComponentB extends React.Component{}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components', () => { - const result = findComponentsInSource( - `import Component from 'classDec'; - export default Component;`, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - - describe('forwardRef components', () => { - test('finds forwardRef components', () => { - const result = findComponentsInSource(` - import React from 'react'; - import PropTypes from 'prop-types'; - import extendStyles from 'enhancers/extendStyles'; - - const ColoredView = React.forwardRef((props, ref) => ( -
- )); - - export default extendStyles(ColoredView); - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds none inline forwardRef components', () => { - const result = findComponentsInSource(` - import React from 'react'; - import PropTypes from 'prop-types'; - import extendStyles from 'enhancers/extendStyles'; - - function ColoredView(props, ref) { - return
- } - - const ForwardedColoredView = React.forwardRef(ColoredView); - - export default ForwardedColoredView - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components', () => { - const result = findComponentsInSource( - `import Component from 'forwardRef'; - export default Component;`, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - }); - - describe('export var foo = , ...;', () => { - describe('React.createClass', () => { - test('finds named exports 1', () => { - const result = findComponentsInSource(` - var React = require("React"); - export var somethingElse = 42, Component = React.createClass({}); - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds named exports 2', () => { - const result = findComponentsInSource(` - var React = require("React"); - export let Component = React.createClass({}), somethingElse = 42; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds named exports 3', () => { - const result = findComponentsInSource(` - var React = require("React"); - export const something = 21, - Component = React.createClass({}), - somethingElse = 42; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds named exports 4', () => { - const result = findComponentsInSource(` - var React = require("React"); - export var somethingElse = function() {}; - export let Component = React.createClass({}); - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple components', () => { - const result = findComponentsInSource(` - var R = require("React"); - export var ComponentA = R.createClass({}), - ComponentB = R.createClass({}); - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple components with separate export statements', () => { - const result = findComponentsInSource(` - var R = require("React"); - export var ComponentA = R.createClass({}); - var ComponentB = R.createClass({}); - export {ComponentB}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds only exported components', () => { - const result = findComponentsInSource(` - var R = require("React"); - var ComponentA = R.createClass({}); - export let ComponentB = R.createClass({}); - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components', () => { - const result = findComponentsInSource( - `import Component from 'createClass'; - export let ComponentA = Component; - export let ComponentB = Component;`, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - - describe('class definition', () => { - test('finds named exports 1', () => { - const result = findComponentsInSource(` - import React from 'React'; - export var somethingElse = 42, - Component = class extends React.Component {}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds named exports 2', () => { - const result = findComponentsInSource(` - import React from 'React'; - export let Component = class extends React.Component {}, - somethingElse = 42; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds named exports 3', () => { - const result = findComponentsInSource(` - import React from 'React'; - export const something = 21, - Component = class extends React.Component {}, - somethingElse = 42; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds named exports 4', () => { - const result = findComponentsInSource(` - import React from 'React'; - export var somethingElse = function() {}; - export let Component = class extends React.Component {}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple components', () => { - const result = findComponentsInSource(` - import React from 'React'; - export var ComponentA = class extends React.Component {}; - export var ComponentB = class extends React.Component {}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple components with assigned component', () => { - const result = findComponentsInSource(` - import React from 'React'; - export var ComponentA = class extends React.Component {}; - var ComponentB = class extends React.Component {}; - export {ComponentB}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds only exported components', () => { - const result = findComponentsInSource(` - import React from 'React'; - var ComponentA = class extends React.Component {} - export var ComponentB = class extends React.Component {}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components', () => { - const result = findComponentsInSource( - ` - import Component from 'classDec'; - export let ComponentA = Component; - export let ComponentB = Component; - `, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - - describe('stateless components', () => { - test('finds named exports 1', () => { - const result = findComponentsInSource(` - import React from 'React'; - export var somethingElse = 42, - Component = () =>
; - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components 2', () => { - const result = findComponentsInSource(` - import React from 'React'; - export let Component = () =>
, - somethingElse = 42; - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components 3', () => { - const result = findComponentsInSource(` - import React from 'React'; - export const something = 21, - Component = () =>
, - somethingElse = 42; - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components 4', () => { - const result = findComponentsInSource(` - import React from 'React'; - export var somethingElse = function() {}; - export let Component = () =>
- `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple components', () => { - const result = findComponentsInSource(` - import React from 'React'; - export var ComponentA = () =>
- export var ComponentB = () =>
- `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple components with named export', () => { - const result = findComponentsInSource(` - import React from 'React'; - export var ComponentA = () =>
- var ComponentB = () =>
- export {ComponentB}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds only exported components', () => { - const result = findComponentsInSource(` - import React from 'React'; - var ComponentA = class extends React.Component {} - export var ComponentB = function() { return
; }; - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components', () => { - const result = findComponentsInSource( - `import Component1 from 'statelessJsx'; - import Component2 from 'statelessCreateElement'; - export var ComponentA = Component1, ComponentB = Component2;`, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - - describe('forwardRef components', () => { - test('finds forwardRef components', () => { - const result = findComponentsInSource(` - import React from 'react'; - import PropTypes from 'prop-types'; - import extendStyles from 'enhancers/extendStyles'; - - export const ColoredView = extendStyles(React.forwardRef((props, ref) => ( -
- ))); - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components', () => { - const result = findComponentsInSource( - ` - import Component from 'forwardRef'; - export let ComponentA = Component; - export let ComponentB = Component; - `, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - }); - - describe('export {};', () => { - describe('React.createClass', () => { - test('finds exported specifiers', () => { - const result = findComponentsInSource(` - var React = require("React"); - var foo = 42; - var Component = React.createClass({}); - export {foo, Component} - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds exported specifiers 2', () => { - const result = findComponentsInSource(` - import React from "React" - var foo = 42; - var Component = React.createClass({}); - export {Component, foo} - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds exported specifiers 3', () => { - const result = findComponentsInSource(` - import React, { createElement } from "React" - var foo = 42; - var baz = 21; - var Component = React.createClass({}); - export {foo, Component as bar, baz} - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple components', () => { - const result = findComponentsInSource(` - var R = require("React"); - var ComponentA = R.createClass({}); - var ComponentB = R.createClass({}); - export {ComponentA as foo, ComponentB}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple components with hocs', () => { - const result = findComponentsInSource(` - var R = require("React"); - var ComponentA = hoc(R.createClass({})); - var ComponentB = hoc(R.createClass({})); - export {ComponentA as foo, ComponentB}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds only exported components', () => { - const result = findComponentsInSource(` - var R = require("React"); - var ComponentA = R.createClass({}); - var ComponentB = R.createClass({}); - export {ComponentA} - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds exported components only once', () => { - const result = findComponentsInSource(` - var R = require("React"); - var ComponentA = R.createClass({}); - export {ComponentA as foo, ComponentA as bar}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components', () => { - const result = findComponentsInSource( - `import Component from 'createClass'; - export { Component, Component as ComponentB };`, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - - describe('class definition', () => { - test('finds exported specifiers 1', () => { - const result = findComponentsInSource(` - import React from 'React'; - var foo = 42; - var Component = class extends React.Component {}; - export {foo, Component}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds exported specifiers 2', () => { - const result = findComponentsInSource(` - import React from 'React'; - var foo = 42; - var Component = class extends React.Component {}; - export {Component, foo}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds exported specifiers 3', () => { - const result = findComponentsInSource(` - import React from 'React'; - var foo = 42; - var baz = 21; - var Component = class extends React.Component {}; - export {foo, Component as bar, baz}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple components', () => { - const result = findComponentsInSource(` - import React from 'React'; - var ComponentA = class extends React.Component {}; - var ComponentB = class extends React.Component {}; - export {ComponentA as foo, ComponentB}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple components with hocs', () => { - const result = findComponentsInSource(` - import React from 'React'; - class ComponentA extends React.Component {}; - class ComponentB extends React.Component {}; - var WrappedA = hoc(ComponentA); - var WrappedB = hoc(ComponentB); - export {WrappedA, WrappedB}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds only exported components', () => { - const result = findComponentsInSource(` - import React from 'React'; - var ComponentA = class extends React.Component {}; - var ComponentB = class extends React.Component {}; - export {ComponentA}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds exported components only once', () => { - const result = findComponentsInSource(` - import React from 'React'; - var ComponentA = class extends React.Component {}; - var ComponentB = class extends React.Component {}; - export {ComponentA as foo, ComponentA as bar}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components', () => { - const result = findComponentsInSource( - ` - import Component from 'classDec'; - export { Component, Component as ComponentB }; - `, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - - describe('stateless components', () => { - test('finds exported specifiers 1', () => { - const result = findComponentsInSource(` - import React from 'React'; - var foo = 42; - function Component() { return
; } - export {foo, Component}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds exported specifiers 2', () => { - const result = findComponentsInSource(` - import React from 'React'; - var foo = 42; - var Component = () =>
; - export {Component, foo}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds exported specifiers 3', () => { - const result = findComponentsInSource(` - import React from 'React'; - var foo = 42; - var baz = 21; - var Component = function () { return
; } - export {foo, Component as bar, baz}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple components', () => { - const result = findComponentsInSource(` - import React from 'React'; - var ComponentA = () =>
; - function ComponentB() { return
; } - export {ComponentA as foo, ComponentB}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds only exported components', () => { - const result = findComponentsInSource(` - import React from 'React'; - var ComponentA = () =>
; - var ComponentB = () =>
; - export {ComponentA}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds exported components only once', () => { - const result = findComponentsInSource(` - import React from 'React'; - var ComponentA = () =>
; - var ComponentB = () =>
; - export {ComponentA as foo, ComponentA as bar}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components', () => { - const result = findComponentsInSource( - ` - import ComponentA from 'statelessJsx'; - import ComponentB from 'statelessCreateElement'; - export { ComponentA, ComponentB }; - `, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - - describe('forwardRef components', () => { - test('finds forwardRef components', () => { - const result = findComponentsInSource(` - import React from 'react'; - import PropTypes from 'prop-types'; - import extendStyles from 'enhancers/extendStyles'; - - const ColoredView = extendStyles(React.forwardRef((props, ref) => ( -
- ))); - - export { ColoredView } - `); - - expect(result).toMatchSnapshot(); - }); - - test('supports imported components', () => { - const result = findComponentsInSource( - ` - import Component from 'forwardRef'; - export { Component, Component as ComponentB }; - `, - mockImporter, - ); - - expect(result).toMatchSnapshot(); - }); - }); - }); - - describe('export ;', () => { - describe('class definition', () => { - test('finds named exports', () => { - const result = findComponentsInSource(` - import React from 'React'; - export var foo = 42; - export class Component extends React.Component {}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple components', () => { - const result = findComponentsInSource(` - import React from 'React'; - export class ComponentA extends React.Component {}; - export class ComponentB extends React.Component {}; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds only exported components', () => { - const result = findComponentsInSource(` - import React from 'React'; - class ComponentA extends React.Component {}; - export class ComponentB extends React.Component {}; - `); - - expect(result).toMatchSnapshot(); - }); - }); - - describe('function declaration', () => { - test('finds named exports', () => { - const result = findComponentsInSource(` - import React from 'React'; - export var foo = 42; - export function Component() { return
; }; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds multiple components', () => { - const result = findComponentsInSource(` - import React from 'React'; - export function ComponentA() { return
; }; - export function ComponentB() { return
; }; - `); - - expect(result).toMatchSnapshot(); - }); - - test('finds only exported components', () => { - const result = findComponentsInSource(` - import React from 'React'; - function ComponentA() { return
; } - export function ComponentB() { return
; }; - `); - - expect(result).toMatchSnapshot(); - }); - }); - }); - }); - }); - - describe('limit 1', () => { - const resolver = new FindExportedDefinitionsResolver({ limit: 1 }); - - function findComponentsInSource( - source: string, - importer = noopImporter, - ): NodePath[] { - return resolver.resolve(parse(source, {}, importer, true)); - } - const mockImporter = makeMockImporter({ - createClass: (stmtLast) => - stmtLast(` - import React from 'react' - export default React.createClass({}) - `).get('declaration'), - - classDec: (stmtLast) => - stmtLast(` - import React from 'react' - export default class Component extends React.Component {} - `).get('declaration'), - - classExpr: (stmtLast) => - stmtLast(` - import React from 'react' - var Component = class extends React.Component {} - export default Component - `).get('declaration'), - - statelessJsx: (stmtLast) => - stmtLast(`export default () =>
`).get('declaration'), - - statelessCreateElement: (stmtLast) => - stmtLast(` - import React from 'react' - export default () => React.createElement('div', {}) - `).get('declaration'), - - forwardRef: (stmtLast) => - stmtLast(` - import React from 'react' - export default React.forwardRef((props, ref) => ( -
- )) - `).get('declaration'), - }); - - describe('CommonJS module exports', () => { - describe('React.createClass', () => { - test('finds React.createClass', () => { - const source = ` - var React = require("React"); - var Component = React.createClass({}); - module.exports = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('finds React.createClass with hoc', () => { - const source = ` - var React = require("React"); - var Component = React.createClass({}); - module.exports = hoc(Component); - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('finds React.createClass with hoc and args', () => { - const source = ` - var React = require("React"); - var Component = React.createClass({}); - module.exports = hoc(arg1, arg2)(Component); - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('finds React.createClass with two hocs', () => { - const source = ` - var React = require("React"); - var Component = React.createClass({}); - module.exports = hoc2(arg2b, arg2b)( - hoc1(arg1a, arg2a)(Component) - ); - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('finds React.createClass with three hocs', () => { - const source = ` - var React = require("React"); - var Component = React.createClass({}); - module.exports = hoc3(arg3a, arg3b)( - hoc2(arg2b, arg2b)( - hoc1(arg1a, arg2a)(Component) - ) - ); - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('finds React.createClass, independent of the var name', () => { - const source = ` - var R = require("React"); - var Component = R.createClass({}); - module.exports = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('does not process X.createClass of other modules', () => { - const source = ` - var R = require("NoReact"); - var Component = R.createClass({}); - module.exports = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(0); - }); - - test('resolves an imported variable to React.createClass', () => { - const source = ` - import Component from 'createClass'; - module.exports = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(0); - }); - }); - - describe('class definitions', () => { - test('finds class declarations', () => { - const source = ` - var React = require("React"); - class Component extends React.Component {} - module.exports = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - - test('finds class expression', () => { - const source = ` - var React = require("React"); - var Component = class extends React.Component {} - module.exports = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassExpression'); - }); - - test('finds class definition, independent of the var name', () => { - const source = ` - var R = require("React"); - class Component extends R.Component {} - module.exports = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - - test('resolves an imported variable to class declaration', () => { - const source = ` - import Component from 'classDec'; - module.exports = Component; - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - - test('resolves an imported variable to class expression', () => { - const source = ` - import Component from 'classExpr'; - module.exports = Component; - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassExpression'); - }); - }); - - describe('stateless components', () => { - test('finds stateless component with JSX', () => { - const source = ` - var React = require("React"); - var Component = () =>
; - module.exports = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('finds stateless components with React.createElement, independent of the var name', () => { - const source = ` - var R = require("React"); - var Component = () => R.createElement('div', {}); - module.exports = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('does not process X.createElement of other modules', () => { - const source = ` - var R = require("NoReact"); - var Component = () => R.createElement({}); - module.exports = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(0); - }); - - test('resolves an imported stateless component with JSX', () => { - const source = ` - import Component from 'statelessJsx'; - module.exports = Component; - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('resolves an imported stateless component with React.createElement', () => { - const source = ` - import Component from 'statelessCreateElement'; - module.exports = Component; - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - }); - - describe('module.exports = ; / exports.foo = ;', () => { - describe('React.createClass', () => { - test('finds assignments to exports', () => { - const source = ` - var R = require("React"); - var Component = R.createClass({}); - exports.foo = 42; - exports.Component = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('errors if multiple components are exported', () => { - const source = ` - var R = require("React"); - var ComponentA = R.createClass({}); - var ComponentB = R.createClass({}); - exports.ComponentA = ComponentA; - exports.ComponentB = ComponentB; - `; - - expect(() => findComponentsInSource(source)).toThrow(); - }); - - test('accepts multiple definitions if only one is exported on exports', () => { - const source = ` - var R = require("React"); - var ComponentA = R.createClass({}); - var ComponentB = R.createClass({}); - exports.ComponentB = ComponentB; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('accepts multiple definitions if only one is exported', () => { - const source = ` - var R = require("React"); - var ComponentA = R.createClass({}); - var ComponentB = R.createClass({}); - module.exports = ComponentB; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('supports imported components', () => { - const source = ` - import Component from 'createClass'; - exports.ComponentB = Component; - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - }); - - describe('class definition', () => { - test('finds assignments to exports', () => { - const source = ` - var R = require("React"); - class Component extends R.Component {} - exports.foo = 42; - exports.Component = Component; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - - test('errors if multiple components are exported', () => { - const source = ` - var R = require("React"); - class ComponentA extends R.Component {} - class ComponentB extends R.Component {} - exports.ComponentA = ComponentA; - exports.ComponentB = ComponentB; - `; - - expect(() => findComponentsInSource(source)).toThrow(); - }); - - test('accepts multiple definitions if only one is exported', () => { - let source = ` - var R = require("React"); - class ComponentA extends R.Component {} - class ComponentB extends R.Component {} - exports.ComponentB = ComponentB; - `; - - let result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - - source = ` - var R = require("React"); - class ComponentA extends R.Component {} - class ComponentB extends R.Component {} - module.exports = ComponentB; - `; - - result = findComponentsInSource(source); - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - - test('supports imported components', () => { - const source = ` - import Component from 'classDec'; - exports.ComponentB = Component; - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - }); - }); - }); - - describe('ES6 export declarations', () => { - describe('export default ;', () => { - describe('React.createClass', () => { - test('finds default export', () => { - const source = ` - var React = require("React"); - var Component = React.createClass({}); - export default Component - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('finds default export inline', () => { - const source = ` - var React = require("React"); - export default React.createClass({}); - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('errors if multiple components are exported', () => { - const source = ` - import React, { createElement } from "React" - export var Component = React.createClass({}) - export default React.createClass({}); - `; - - expect(() => findComponentsInSource(source)).toThrow(); - }); - - test('errors if multiple components are exported with named export', () => { - const source = ` - import React, { createElement } from "React" - var Component = React.createClass({}) - export {Component}; - export default React.createClass({}); - `; - - expect(() => findComponentsInSource(source)).toThrow(); - }); - - test('accepts multiple definitions if only one is exported', () => { - const source = ` - import React, { createElement } from "React" - var Component = React.createClass({}) - export default React.createClass({}); - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('supports imported components', () => { - const source = ` - import Component from 'createClass'; - export default Component; - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - }); - - describe('class definition', () => { - test('finds default export', () => { - let source = ` - import React from 'React'; - class Component extends React.Component {} - export default Component; - `; - - let result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - - source = ` - import React from 'React'; - export default class Component extends React.Component {}; - `; - - result = findComponentsInSource(source); - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - - test('finds default export with hoc', () => { - const source = ` - import React from 'React'; - class Component extends React.Component {} - export default hoc(Component); - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - - test('finds default export with hoc and args', () => { - const source = ` - import React from 'React'; - class Component extends React.Component {} - export default hoc(arg1, arg2)(Component); - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - - test('finds default export with two hocs', () => { - const source = ` - import React from 'React'; - class Component extends React.Component {} - export default hoc2(arg2b, arg2b)( - hoc1(arg1a, arg2a)(Component) - ); - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - - test('errors if multiple components are exported', () => { - let source = ` - import React from 'React'; - export var Component = class extends React.Component {}; - export default class ComponentB extends React.Component{}; - `; - - expect(() => findComponentsInSource(source)).toThrow(); - - source = ` - import React from 'React'; - var Component = class extends React.Component {}; - export {Component}; - export default class ComponentB extends React.Component{}; - `; - expect(() => findComponentsInSource(source)).toThrow(); - }); - - test('accepts multiple definitions if only one is exported', () => { - const source = ` - import React from 'React'; - var Component = class extends React.Component {}; - export default class ComponentB extends React.Component{}; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - - test('supports imported components', () => { - const source = ` - import Component from 'classDec'; - export default Component; - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - }); - }); - - describe('export var foo = , ...;', () => { - describe('React.createClass', () => { - test('finds named exports with export var', () => { - const source = ` - var React = require("React"); - export var somethingElse = 42, Component = React.createClass({}); - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('finds named exports with export let', () => { - const source = ` - var React = require("React"); - export let Component = React.createClass({}), somethingElse = 42; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('finds named exports with export const', () => { - const source = ` - var React = require("React"); - export const something = 21, - Component = React.createClass({}), - somethingElse = 42; - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('finds named exports with export let and additional export', () => { - const source = ` - var React = require("React"); - export var somethingElse = function() {}; - export let Component = React.createClass({}); - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('errors if multiple components are exported', () => { - let source = ` - var R = require("React"); - export var ComponentA = R.createClass({}), - ComponentB = R.createClass({}); - `; - - expect(() => findComponentsInSource(source)).toThrow(); - - source = ` - var R = require("React"); - export var ComponentA = R.createClass({}); - var ComponentB = R.createClass({}); - export {ComponentB}; - `; - - expect(() => findComponentsInSource(source)).toThrow(); - }); - - test('accepts multiple definitions if only one is exported', () => { - const source = ` - var R = require("React"); - var ComponentA = R.createClass({}); - export let ComponentB = R.createClass({}); - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('supports imported components', () => { - const source = ` - import Component from 'createClass'; - export let ComponentB = Component; - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - }); - - describe('class definition', () => { - test('finds named exports', () => { - let source = ` - import React from 'React'; - export var somethingElse = 42, - Component = class extends React.Component {}; - `; - let result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassExpression'); - - source = ` - import React from 'React'; - export let Component = class extends React.Component {}, - somethingElse = 42; - `; - result = findComponentsInSource(source); - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassExpression'); - - source = ` - import React from 'React'; - export const something = 21, - Component = class extends React.Component {}, - somethingElse = 42; - `; - result = findComponentsInSource(source); - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassExpression'); - - source = ` - import React from 'React'; - export var somethingElse = function() {}; - export let Component = class extends React.Component {}; - `; - result = findComponentsInSource(source); - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassExpression'); - }); - - test('errors if multiple components are exported', () => { - let source = ` - import React from 'React'; - export var ComponentA = class extends React.Component {}; - export var ComponentB = class extends React.Component {}; - `; - - expect(() => findComponentsInSource(source)).toThrow(); - - source = ` - import React from 'React'; - export var ComponentA = class extends React.Component {}; - var ComponentB = class extends React.Component {}; - export {ComponentB}; - `; - expect(() => findComponentsInSource(source)).toThrow(); - }); - - test('accepts multiple definitions if only one is exported', () => { - const source = ` - import React from 'React'; - var ComponentA = class extends React.Component {} - export var ComponentB = class extends React.Component {}; - `; - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassExpression'); - }); - - test('supports imported components', () => { - const source = ` - import Component from 'classDec'; - export let ComponentB = Component; - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - }); - - describe('stateless components', () => { - test('finds named exports', () => { - let source = ` - import React from 'React'; - export var somethingElse = 42, - Component = () =>
; - `; - let result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ArrowFunctionExpression'); - - source = ` - import React from 'React'; - export let Component = () =>
, - somethingElse = 42; - `; - result = findComponentsInSource(source); - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ArrowFunctionExpression'); - - source = ` - import React from 'React'; - export const something = 21, - Component = () =>
, - somethingElse = 42; - `; - result = findComponentsInSource(source); - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ArrowFunctionExpression'); - - source = ` - import React from 'React'; - export var somethingElse = function() {}; - export let Component = () =>
- `; - result = findComponentsInSource(source); - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ArrowFunctionExpression'); - }); - - test('errors if multiple components are exported', () => { - let source = ` - import React from 'React'; - export var ComponentA = () =>
- export var ComponentB = () =>
- `; - - expect(() => findComponentsInSource(source)).toThrow(); - - source = ` - import React from 'React'; - export var ComponentA = () =>
- var ComponentB = () =>
- export {ComponentB}; - `; - expect(() => findComponentsInSource(source)).toThrow(); - }); - - test('accepts multiple definitions if only one is exported', () => { - const source = ` - import React from 'React'; - var ComponentA = class extends React.Component {} - export var ComponentB = function() { return
; }; - `; - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('FunctionExpression'); - }); - - test('supports imported components', () => { - let source = ` - import Component from 'statelessJsx'; - export var ComponentA = Component; - `; - - let result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ArrowFunctionExpression'); - - source = ` - import Component from 'statelessCreateElement'; - export var ComponentB = Component; - `; - - result = findComponentsInSource(source, mockImporter); - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ArrowFunctionExpression'); - }); - }); - }); - - describe('export {};', () => { - describe('React.createClass', () => { - test('finds exported specifiers 1', () => { - const source = ` - var React = require("React"); - var foo = 42; - var Component = React.createClass({}); - export {foo, Component} - `; - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('finds exported specifiers 2', () => { - const source = ` - import React from "React" - var foo = 42; - var Component = React.createClass({}); - export {Component, foo} - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('finds exported specifiers 3', () => { - const source = ` - import React, { createElement } from "React" - var foo = 42; - var baz = 21; - var Component = React.createClass({}); - export {foo, Component as bar, baz} - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('errors if multiple components are exported', () => { - const source = ` - var R = require("React"); - var ComponentA = R.createClass({}); - var ComponentB = R.createClass({}); - export {ComponentA as foo, ComponentB}; - `; - - expect(() => findComponentsInSource(source)).toThrow(); - }); - - test('accepts multiple definitions if only one is exported', () => { - const source = ` - var R = require("React"); - var ComponentA = R.createClass({}); - var ComponentB = R.createClass({}); - export {ComponentA} - `; - - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - - test('supports imported components', () => { - const source = ` - import Component from 'createClass'; - export { Component }; - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - }); - }); - - describe('class definition', () => { - test('finds exported specifiers', () => { - let source = ` - import React from 'React'; - var foo = 42; - var Component = class extends React.Component {}; - export {foo, Component}; - `; - let result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassExpression'); - - source = ` - import React from 'React'; - var foo = 42; - var Component = class extends React.Component {}; - export {Component, foo}; - `; - result = findComponentsInSource(source); - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassExpression'); - - source = ` - import React from 'React'; - var foo = 42; - var baz = 21; - var Component = class extends React.Component {}; - export {foo, Component as bar, baz}; - `; - result = findComponentsInSource(source); - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassExpression'); - }); - - test('errors if multiple components are exported', () => { - const source = ` - import React from 'React'; - var ComponentA = class extends React.Component {}; - var ComponentB = class extends React.Component {}; - export {ComponentA as foo, ComponentB}; - `; - - expect(() => findComponentsInSource(source)).toThrow(); - }); - - test('accepts multiple definitions if only one is exported', () => { - const source = ` - import React from 'React'; - var ComponentA = class extends React.Component {}; - var ComponentB = class extends React.Component {}; - export {ComponentA}; - `; - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassExpression'); - }); - - test('supports imported components', () => { - const source = ` - import Component from 'classDec'; - export { Component }; - `; - - const result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - }); - - describe('stateless components', () => { - test('finds exported specifiers', () => { - let source = ` - import React from 'React'; - var foo = 42; - function Component() { return
; } - export {foo, Component}; - `; - let result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('FunctionDeclaration'); - - source = ` - import React from 'React'; - var foo = 42; - var Component = () =>
; - export {Component, foo}; - `; - result = findComponentsInSource(source); - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ArrowFunctionExpression'); - - source = ` - import React from 'React'; - var foo = 42; - var baz = 21; - var Component = function () { return
; } - export {foo, Component as bar, baz}; - `; - result = findComponentsInSource(source); - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('FunctionExpression'); - }); - - test('errors if multiple components are exported', () => { - const source = ` - import React from 'React'; - var ComponentA = () =>
; - function ComponentB() { return
; } - export {ComponentA as foo, ComponentB}; - `; - - expect(() => findComponentsInSource(source)).toThrow(); - }); - - test('accepts multiple definitions if only one is exported', () => { - const source = ` - import React from 'React'; - var ComponentA = () =>
; - var ComponentB = () =>
; - export {ComponentA}; - `; - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ArrowFunctionExpression'); - }); - - test('supports imported components', () => { - let source = ` - import Component from 'statelessJsx'; - export { Component as ComponentA }; - `; - - let result = findComponentsInSource(source, mockImporter); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ArrowFunctionExpression'); - - source = ` - import Component from 'statelessCreateElement'; - export { Component as ComponentB }; - `; - - result = findComponentsInSource(source, mockImporter); - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ArrowFunctionExpression'); - }); - }); - }); - - // Only applies to classes - describe('export ;', () => { - test('finds named exports', () => { - const source = ` - import React from 'React'; - export var foo = 42; - export class Component extends React.Component {}; - `; - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - - test('errors if multiple components are exported', () => { - const source = ` - import React from 'React'; - export class ComponentA extends React.Component {}; - export class ComponentB extends React.Component {}; - `; - - expect(() => findComponentsInSource(source)).toThrow(); - }); - - test('accepts multiple definitions if only one is exported', () => { - const source = ` - import React from 'React'; - class ComponentA extends React.Component {}; - export class ComponentB extends React.Component {}; - `; - const result = findComponentsInSource(source); - - expect(Array.isArray(result)).toBe(true); - expect(result).toHaveLength(1); - expect(result[0].node.type).toBe('ClassDeclaration'); - }); - }); - }); - }); -}); diff --git a/packages/react-docgen/src/resolver/__tests__/__snapshots__/FindAnnotatedDefinitionsResolver-test.ts.snap b/packages/react-docgen/src/resolver/__tests__/__snapshots__/FindAnnotatedDefinitionsResolver-test.ts.snap deleted file mode 100644 index 3226ea2b977..00000000000 --- a/packages/react-docgen/src/resolver/__tests__/__snapshots__/FindAnnotatedDefinitionsResolver-test.ts.snap +++ /dev/null @@ -1,291 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`FindAnnotatedDefinitionsResolver > class definitions > finds ClassDeclaration with block comment 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "superClass": null, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > class definitions > finds ClassDeclaration with block comment and empty line 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "superClass": null, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > class definitions > finds ClassDeclaration with line comment 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "superClass": null, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > class definitions > finds ClassDeclaration with line comment and empty line 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "superClass": null, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > class definitions > finds ClassExpression 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": null, - "type": "ClassExpression", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > class definitions > finds ClassExpression with assignment 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": null, - "type": "ClassExpression", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > finds component wrapped in HOC 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > finds component wrapped in function 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": null, - "type": "ClassExpression", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > finds component wrapped in two HOCs 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > finds default exported component 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > finds function parameter with annotation 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > finds named exported component 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > stateless components > finds ArrowFunctionExpression 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > stateless components > finds FunctionDeclaration 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "params": [], - "type": "FunctionDeclaration", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > stateless components > finds FunctionExpression 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": null, - "params": [], - "type": "FunctionExpression", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > stateless components > finds ObjectMethod 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [], - "directives": [], - "type": "BlockStatement", - }, - "computed": false, - "generator": false, - "id": null, - "key": Node { - "name": "component", - "type": "Identifier", - }, - "kind": "method", - "method": true, - "params": [], - "type": "ObjectMethod", - }, -] -`; - -exports[`FindAnnotatedDefinitionsResolver > stateless components > finds ObjectProperty 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": null, - "params": [], - "type": "FunctionExpression", - }, -] -`; diff --git a/packages/react-docgen/src/resolver/__tests__/__snapshots__/FindExportedDefinitionsResolver-test.ts.snap b/packages/react-docgen/src/resolver/__tests__/__snapshots__/FindExportedDefinitionsResolver-test.ts.snap deleted file mode 100644 index 6a6d09e27c4..00000000000 --- a/packages/react-docgen/src/resolver/__tests__/__snapshots__/FindExportedDefinitionsResolver-test.ts.snap +++ /dev/null @@ -1,3221 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > React.createClass > does not process X.createClass of other modules 1`] = `[]`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > React.createClass > finds React.createClass 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > React.createClass > finds React.createClass, independent of the var name 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > React.createClass > resolves an imported variable to React.createClass 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > class definitions > finds class declarations 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > class definitions > finds class definition, independent of the var name 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "R", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > class definitions > finds class expression 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > class definitions > resolves an imported variable to class declaration 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > class definitions > resolves an imported variable to class expression 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > forwardRef components > finds forwardRef components 1`] = ` -[ - Node { - "arguments": [ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "extra": { - "parenStart": 209, - "parenthesized": true, - }, - "openingElement": Node { - "attributes": [ - Node { - "name": Node { - "name": "ref", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "name": "ref", - "type": "Identifier", - }, - "type": "JSXExpressionContainer", - }, - }, - Node { - "name": Node { - "name": "style", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "properties": [ - Node { - "computed": false, - "key": Node { - "name": "backgroundColor", - "type": "Identifier", - }, - "method": false, - "shorthand": false, - "type": "ObjectProperty", - "value": Node { - "computed": false, - "object": Node { - "name": "props", - "type": "Identifier", - }, - "property": Node { - "name": "color", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - }, - ], - "type": "ObjectExpression", - }, - "type": "JSXExpressionContainer", - }, - }, - ], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [ - Node { - "name": "props", - "type": "Identifier", - }, - Node { - "name": "ref", - "type": "Identifier", - }, - ], - "type": "ArrowFunctionExpression", - }, - ], - "callee": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "forwardRef", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "CallExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > forwardRef components > finds none inline forwardRef components 1`] = ` -[ - Node { - "arguments": [ - Node { - "name": "ColoredView", - "type": "Identifier", - }, - ], - "callee": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "forwardRef", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "CallExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > forwardRef components > resolves an imported forwardRef component 1`] = ` -[ - Node { - "arguments": [ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "extra": { - "parenStart": 87, - "parenthesized": true, - }, - "openingElement": Node { - "attributes": [ - Node { - "name": Node { - "name": "ref", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "name": "ref", - "type": "Identifier", - }, - "type": "JSXExpressionContainer", - }, - }, - Node { - "name": Node { - "name": "style", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "properties": [ - Node { - "computed": false, - "key": Node { - "name": "backgroundColor", - "type": "Identifier", - }, - "method": false, - "shorthand": false, - "type": "ObjectProperty", - "value": Node { - "computed": false, - "object": Node { - "name": "props", - "type": "Identifier", - }, - "property": Node { - "name": "color", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - }, - ], - "type": "ObjectExpression", - }, - "type": "JSXExpressionContainer", - }, - }, - ], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [ - Node { - "name": "props", - "type": "Identifier", - }, - Node { - "name": "ref", - "type": "Identifier", - }, - ], - "type": "ArrowFunctionExpression", - }, - ], - "callee": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "forwardRef", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "CallExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > module.exports = ; / exports.foo = ; > React.createClass > finds assignments to exports 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > module.exports = ; / exports.foo = ; > React.createClass > finds exported components only once 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > module.exports = ; / exports.foo = ; > React.createClass > finds multiple exported components 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > module.exports = ; / exports.foo = ; > React.createClass > finds multiple exported components with hocs 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > module.exports = ; / exports.foo = ; > React.createClass > finds only exported components 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > module.exports = ; / exports.foo = ; > React.createClass > finds only exported components on export 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > module.exports = ; / exports.foo = ; > React.createClass > supports imported components 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > module.exports = ; / exports.foo = ; > class definition > finds assignments to exports 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "R", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > module.exports = ; / exports.foo = ; > class definition > finds exported components only once 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "ComponentA", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "R", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > module.exports = ; / exports.foo = ; > class definition > finds multiple exported components 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "ComponentA", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "R", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "ComponentB", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "R", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > module.exports = ; / exports.foo = ; > class definition > finds only exported components 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "ComponentB", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "R", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > module.exports = ; / exports.foo = ; > class definition > finds only exported components on export 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "ComponentB", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "R", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > module.exports = ; / exports.foo = ; > class definition > supports imported components 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > stateless components > does not process X.createElement of other modules 1`] = `[]`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > stateless components > finds stateless component with JSX 1`] = ` -[ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > stateless components > finds stateless components with React.createElement, independent of the var name 1`] = ` -[ - Node { - "async": false, - "body": Node { - "arguments": [ - Node { - "extra": { - "raw": "'div'", - "rawValue": "div", - }, - "type": "StringLiteral", - "value": "div", - }, - Node { - "properties": [], - "type": "ObjectExpression", - }, - ], - "callee": Node { - "computed": false, - "object": Node { - "name": "R", - "type": "Identifier", - }, - "property": Node { - "name": "createElement", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "CallExpression", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > stateless components > resolves an imported stateless component with JSX 1`] = ` -[ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > CommonJS module exports > stateless components > resolves an imported stateless component with React.createElement 1`] = ` -[ - Node { - "async": false, - "body": Node { - "arguments": [ - Node { - "extra": { - "raw": "'div'", - "rawValue": "div", - }, - "type": "StringLiteral", - "value": "div", - }, - Node { - "properties": [], - "type": "ObjectExpression", - }, - ], - "callee": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "createElement", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "CallExpression", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export ; > class definition > finds multiple components 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "ComponentA", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "ComponentB", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export ; > class definition > finds named exports 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export ; > class definition > finds only exported components 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "ComponentB", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export ; > function declaration > finds multiple components 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [ - Node { - "argument": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "type": "ReturnStatement", - }, - ], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": Node { - "name": "ComponentA", - "type": "Identifier", - }, - "params": [], - "type": "FunctionDeclaration", - }, - Node { - "async": false, - "body": Node { - "body": [ - Node { - "argument": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "type": "ReturnStatement", - }, - ], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": Node { - "name": "ComponentB", - "type": "Identifier", - }, - "params": [], - "type": "FunctionDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export ; > function declaration > finds named exports 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [ - Node { - "argument": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "type": "ReturnStatement", - }, - ], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "params": [], - "type": "FunctionDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export ; > function declaration > finds only exported components 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [ - Node { - "argument": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "type": "ReturnStatement", - }, - ], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": Node { - "name": "ComponentB", - "type": "Identifier", - }, - "params": [], - "type": "FunctionDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > React.createClass > finds exported components only once 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > React.createClass > finds exported specifiers 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > React.createClass > finds exported specifiers 2 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > React.createClass > finds exported specifiers 3 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > React.createClass > finds multiple components 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > React.createClass > finds multiple components with hocs 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > React.createClass > finds only exported components 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > React.createClass > supports imported components 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > class definition > finds exported components only once 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > class definition > finds exported specifiers 1 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > class definition > finds exported specifiers 2 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > class definition > finds exported specifiers 3 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > class definition > finds multiple components 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > class definition > finds multiple components with hocs 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "ComponentA", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "ComponentB", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > class definition > finds only exported components 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > class definition > supports imported components 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > forwardRef components > finds forwardRef components 1`] = ` -[ - Node { - "arguments": [ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "extra": { - "parenStart": 230, - "parenthesized": true, - }, - "openingElement": Node { - "attributes": [ - Node { - "name": Node { - "name": "ref", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "name": "ref", - "type": "Identifier", - }, - "type": "JSXExpressionContainer", - }, - }, - Node { - "name": Node { - "name": "style", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "properties": [ - Node { - "computed": false, - "key": Node { - "name": "backgroundColor", - "type": "Identifier", - }, - "method": false, - "shorthand": false, - "type": "ObjectProperty", - "value": Node { - "computed": false, - "object": Node { - "name": "props", - "type": "Identifier", - }, - "property": Node { - "name": "color", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - }, - ], - "type": "ObjectExpression", - }, - "type": "JSXExpressionContainer", - }, - }, - ], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [ - Node { - "name": "props", - "type": "Identifier", - }, - Node { - "name": "ref", - "type": "Identifier", - }, - ], - "type": "ArrowFunctionExpression", - }, - ], - "callee": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "forwardRef", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "CallExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > forwardRef components > supports imported components 1`] = ` -[ - Node { - "arguments": [ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "extra": { - "parenStart": 87, - "parenthesized": true, - }, - "openingElement": Node { - "attributes": [ - Node { - "name": Node { - "name": "ref", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "name": "ref", - "type": "Identifier", - }, - "type": "JSXExpressionContainer", - }, - }, - Node { - "name": Node { - "name": "style", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "properties": [ - Node { - "computed": false, - "key": Node { - "name": "backgroundColor", - "type": "Identifier", - }, - "method": false, - "shorthand": false, - "type": "ObjectProperty", - "value": Node { - "computed": false, - "object": Node { - "name": "props", - "type": "Identifier", - }, - "property": Node { - "name": "color", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - }, - ], - "type": "ObjectExpression", - }, - "type": "JSXExpressionContainer", - }, - }, - ], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [ - Node { - "name": "props", - "type": "Identifier", - }, - Node { - "name": "ref", - "type": "Identifier", - }, - ], - "type": "ArrowFunctionExpression", - }, - ], - "callee": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "forwardRef", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "CallExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > stateless components > finds exported components only once 1`] = ` -[ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > stateless components > finds exported specifiers 1 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [ - Node { - "argument": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "type": "ReturnStatement", - }, - ], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "params": [], - "type": "FunctionDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > stateless components > finds exported specifiers 2 1`] = ` -[ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > stateless components > finds exported specifiers 3 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [ - Node { - "argument": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "type": "ReturnStatement", - }, - ], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": null, - "params": [], - "type": "FunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > stateless components > finds multiple components 1`] = ` -[ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, - Node { - "async": false, - "body": Node { - "body": [ - Node { - "argument": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "type": "ReturnStatement", - }, - ], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": Node { - "name": "ComponentB", - "type": "Identifier", - }, - "params": [], - "type": "FunctionDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > stateless components > finds only exported components 1`] = ` -[ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export {}; > stateless components > supports imported components 1`] = ` -[ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, - Node { - "async": false, - "body": Node { - "arguments": [ - Node { - "extra": { - "raw": "'div'", - "rawValue": "div", - }, - "type": "StringLiteral", - "value": "div", - }, - Node { - "properties": [], - "type": "ObjectExpression", - }, - ], - "callee": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "createElement", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "CallExpression", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export default ; > React.createClass > finds default export 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export default ; > React.createClass > finds multiple exported components with export var 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export default ; > React.createClass > finds multiple exported components with named export 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export default ; > React.createClass > finds only exported components 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export default ; > React.createClass > finds reassigned default export 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export default ; > React.createClass > supports imported components 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export default ; > class definition > finds default export 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export default ; > class definition > finds default export inline 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export default ; > class definition > finds multiple exported components with export var 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "ComponentB", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export default ; > class definition > finds multiple exported components with named export 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "ComponentB", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export default ; > class definition > finds only exported components 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "ComponentB", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export default ; > class definition > supports imported components 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export default ; > forwardRef components > finds forwardRef components 1`] = ` -[ - Node { - "arguments": [ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "extra": { - "parenStart": 217, - "parenthesized": true, - }, - "openingElement": Node { - "attributes": [ - Node { - "name": Node { - "name": "ref", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "name": "ref", - "type": "Identifier", - }, - "type": "JSXExpressionContainer", - }, - }, - Node { - "name": Node { - "name": "style", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "properties": [ - Node { - "computed": false, - "key": Node { - "name": "backgroundColor", - "type": "Identifier", - }, - "method": false, - "shorthand": false, - "type": "ObjectProperty", - "value": Node { - "computed": false, - "object": Node { - "name": "props", - "type": "Identifier", - }, - "property": Node { - "name": "color", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - }, - ], - "type": "ObjectExpression", - }, - "type": "JSXExpressionContainer", - }, - }, - ], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [ - Node { - "name": "props", - "type": "Identifier", - }, - Node { - "name": "ref", - "type": "Identifier", - }, - ], - "type": "ArrowFunctionExpression", - }, - ], - "callee": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "forwardRef", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "CallExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export default ; > forwardRef components > finds none inline forwardRef components 1`] = ` -[ - Node { - "arguments": [ - Node { - "name": "ColoredView", - "type": "Identifier", - }, - ], - "callee": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "forwardRef", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "CallExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export default ; > forwardRef components > supports imported components 1`] = ` -[ - Node { - "arguments": [ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "extra": { - "parenStart": 87, - "parenthesized": true, - }, - "openingElement": Node { - "attributes": [ - Node { - "name": Node { - "name": "ref", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "name": "ref", - "type": "Identifier", - }, - "type": "JSXExpressionContainer", - }, - }, - Node { - "name": Node { - "name": "style", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "properties": [ - Node { - "computed": false, - "key": Node { - "name": "backgroundColor", - "type": "Identifier", - }, - "method": false, - "shorthand": false, - "type": "ObjectProperty", - "value": Node { - "computed": false, - "object": Node { - "name": "props", - "type": "Identifier", - }, - "property": Node { - "name": "color", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - }, - ], - "type": "ObjectExpression", - }, - "type": "JSXExpressionContainer", - }, - }, - ], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [ - Node { - "name": "props", - "type": "Identifier", - }, - Node { - "name": "ref", - "type": "Identifier", - }, - ], - "type": "ArrowFunctionExpression", - }, - ], - "callee": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "forwardRef", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "CallExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > React.createClass > finds multiple components 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > React.createClass > finds multiple components with separate export statements 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > React.createClass > finds named exports 1 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > React.createClass > finds named exports 2 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > React.createClass > finds named exports 3 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > React.createClass > finds named exports 4 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > React.createClass > finds only exported components 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > React.createClass > supports imported components 1`] = ` -[ - Node { - "properties": [], - "type": "ObjectExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > class definition > finds multiple components 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > class definition > finds multiple components with assigned component 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > class definition > finds named exports 1 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > class definition > finds named exports 2 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > class definition > finds named exports 3 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > class definition > finds named exports 4 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > class definition > finds only exported components 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": null, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > class definition > supports imported components 1`] = ` -[ - Node { - "body": Node { - "body": [], - "type": "ClassBody", - }, - "id": Node { - "name": "Component", - "type": "Identifier", - }, - "superClass": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "Component", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "ClassDeclaration", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > forwardRef components > finds forwardRef components 1`] = ` -[ - Node { - "arguments": [ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "extra": { - "parenStart": 237, - "parenthesized": true, - }, - "openingElement": Node { - "attributes": [ - Node { - "name": Node { - "name": "ref", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "name": "ref", - "type": "Identifier", - }, - "type": "JSXExpressionContainer", - }, - }, - Node { - "name": Node { - "name": "style", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "properties": [ - Node { - "computed": false, - "key": Node { - "name": "backgroundColor", - "type": "Identifier", - }, - "method": false, - "shorthand": false, - "type": "ObjectProperty", - "value": Node { - "computed": false, - "object": Node { - "name": "props", - "type": "Identifier", - }, - "property": Node { - "name": "color", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - }, - ], - "type": "ObjectExpression", - }, - "type": "JSXExpressionContainer", - }, - }, - ], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [ - Node { - "name": "props", - "type": "Identifier", - }, - Node { - "name": "ref", - "type": "Identifier", - }, - ], - "type": "ArrowFunctionExpression", - }, - ], - "callee": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "forwardRef", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "CallExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > forwardRef components > supports imported components 1`] = ` -[ - Node { - "arguments": [ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "extra": { - "parenStart": 87, - "parenthesized": true, - }, - "openingElement": Node { - "attributes": [ - Node { - "name": Node { - "name": "ref", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "name": "ref", - "type": "Identifier", - }, - "type": "JSXExpressionContainer", - }, - }, - Node { - "name": Node { - "name": "style", - "type": "JSXIdentifier", - }, - "type": "JSXAttribute", - "value": Node { - "expression": Node { - "properties": [ - Node { - "computed": false, - "key": Node { - "name": "backgroundColor", - "type": "Identifier", - }, - "method": false, - "shorthand": false, - "type": "ObjectProperty", - "value": Node { - "computed": false, - "object": Node { - "name": "props", - "type": "Identifier", - }, - "property": Node { - "name": "color", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - }, - ], - "type": "ObjectExpression", - }, - "type": "JSXExpressionContainer", - }, - }, - ], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [ - Node { - "name": "props", - "type": "Identifier", - }, - Node { - "name": "ref", - "type": "Identifier", - }, - ], - "type": "ArrowFunctionExpression", - }, - ], - "callee": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "forwardRef", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "CallExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > stateless components > finds multiple components 1`] = ` -[ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > stateless components > finds multiple components with named export 1`] = ` -[ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > stateless components > finds named exports 1 1`] = ` -[ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > stateless components > finds only exported components 1`] = ` -[ - Node { - "async": false, - "body": Node { - "body": [ - Node { - "argument": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "type": "ReturnStatement", - }, - ], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": null, - "params": [], - "type": "FunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > stateless components > supports imported components 1`] = ` -[ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, - Node { - "async": false, - "body": Node { - "arguments": [ - Node { - "extra": { - "raw": "'div'", - "rawValue": "div", - }, - "type": "StringLiteral", - "value": "div", - }, - Node { - "properties": [], - "type": "ObjectExpression", - }, - ], - "callee": Node { - "computed": false, - "object": Node { - "name": "React", - "type": "Identifier", - }, - "property": Node { - "name": "createElement", - "type": "Identifier", - }, - "type": "MemberExpression", - }, - "type": "CallExpression", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > stateless components > supports imported components 2 1`] = ` -[ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > stateless components > supports imported components 3 1`] = ` -[ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; - -exports[`FindExportedDefinitionsResolver > no limit > ES6 export declarations > export var foo = , ...; > stateless components > supports imported components 4 1`] = ` -[ - Node { - "async": false, - "body": Node { - "children": [], - "closingElement": null, - "openingElement": Node { - "attributes": [], - "name": Node { - "name": "div", - "type": "JSXIdentifier", - }, - "selfClosing": true, - "type": "JSXOpeningElement", - }, - "type": "JSXElement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, -] -`; diff --git a/packages/react-docgen/src/resolver/index.ts b/packages/react-docgen/src/resolver/index.ts deleted file mode 100644 index f4767379c64..00000000000 --- a/packages/react-docgen/src/resolver/index.ts +++ /dev/null @@ -1,46 +0,0 @@ -import ChainResolver from './ChainResolver.js'; -import FindAllDefinitionsResolver from './FindAllDefinitionsResolver.js'; -import FindAnnotatedDefinitionsResolver from './FindAnnotatedDefinitionsResolver.js'; -import FindExportedDefinitionsResolver from './FindExportedDefinitionsResolver.js'; -import type { NodePath } from '@babel/traverse'; -import type FileState from '../FileState.js'; -import type { - ArrowFunctionExpression, - CallExpression, - ClassDeclaration, - ClassExpression, - FunctionDeclaration, - FunctionExpression, - ObjectExpression, - ObjectMethod, -} from '@babel/types'; - -export type StatelessComponentNode = - | ArrowFunctionExpression - | FunctionDeclaration - | FunctionExpression - | ObjectMethod; - -export type ComponentNode = - | CallExpression - | ClassDeclaration - | ClassExpression - | ObjectExpression - | StatelessComponentNode; - -export type ComponentNodePath = NodePath; - -export type ResolverFunction = (file: FileState) => ComponentNodePath[]; - -export interface ResolverClass { - resolve: ResolverFunction; -} - -export type Resolver = ResolverClass | ResolverFunction; - -export { - FindAllDefinitionsResolver, - FindAnnotatedDefinitionsResolver, - FindExportedDefinitionsResolver, - ChainResolver, -}; diff --git a/packages/react-docgen/src/resolver/utils/__tests__/runResolver-test.ts b/packages/react-docgen/src/resolver/utils/__tests__/runResolver-test.ts deleted file mode 100644 index 7c4e67f313b..00000000000 --- a/packages/react-docgen/src/resolver/utils/__tests__/runResolver-test.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { describe, expect, test, vi } from 'vitest'; -import type { - ComponentNodePath, - ResolverClass, -} from '../../../resolver/index.js'; -import runResolver from '../runResolver'; -import FileStateMock from '../../../__mocks__/FileState.js'; - -const createEmptyClassResolver = (path?: ComponentNodePath) => - new (class implements ResolverClass { - resolve = vi.fn(() => { - return path ? [path] : []; - }); - })(); - -const createEmptyFunctionResolver = (path?: ComponentNodePath) => - vi.fn(() => (path ? [path] : [])); - -describe('runResolver', () => { - const fileStateMock = new FileStateMock(); - - test('does run function resolvers', () => { - const resolver = createEmptyFunctionResolver(); - - runResolver(resolver, fileStateMock); - - expect(resolver).toBeCalled(); - expect(resolver).toHaveBeenCalledWith(fileStateMock); - }); - - test('does run class resolvers', () => { - const resolver = createEmptyClassResolver(); - - runResolver(resolver, fileStateMock); - - expect(resolver.resolve).toBeCalled(); - expect(resolver.resolve).toHaveBeenCalledWith(fileStateMock); - }); -}); diff --git a/packages/react-docgen/src/resolver/utils/runResolver.ts b/packages/react-docgen/src/resolver/utils/runResolver.ts deleted file mode 100644 index a8f93a5e042..00000000000 --- a/packages/react-docgen/src/resolver/utils/runResolver.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type FileState from '../../FileState.js'; -import type { Resolver, ResolverClass, ResolverFunction } from '../index.js'; - -function isResolverClass(resolver: Resolver): resolver is ResolverClass { - return typeof resolver === 'object'; -} - -export default function runResolver( - resolver: Resolver, - file: FileState, -): ReturnType { - return isResolverClass(resolver) ? resolver.resolve(file) : resolver(file); -} diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/getClassMemberValuePath-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/getClassMemberValuePath-test.ts.snap deleted file mode 100644 index d51de0b470e..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/getClassMemberValuePath-test.ts.snap +++ /dev/null @@ -1,93 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`getClassMemberValuePath > ClassDeclaration > Getters and Setters > finds getters 1`] = ` -Node { - "async": false, - "body": Node { - "body": [], - "directives": [], - "type": "BlockStatement", - }, - "computed": false, - "generator": false, - "id": null, - "key": Node { - "name": "foo", - "type": "Identifier", - }, - "kind": "get", - "params": [], - "static": false, - "type": "ClassMethod", -} -`; - -exports[`getClassMemberValuePath > ClassDeclaration > MethodDefinitions > finds "normal" method definitions 1`] = ` -Node { - "async": false, - "body": Node { - "body": [], - "directives": [], - "type": "BlockStatement", - }, - "computed": false, - "generator": false, - "id": null, - "key": Node { - "name": "render", - "type": "Identifier", - }, - "kind": "method", - "params": [], - "static": false, - "type": "ClassMethod", -} -`; - -exports[`getClassMemberValuePath > ClassDeclaration > MethodDefinitions > finds computed method definitions with literal keys 1`] = ` -Node { - "async": false, - "body": Node { - "body": [], - "directives": [], - "type": "BlockStatement", - }, - "computed": true, - "generator": false, - "id": null, - "key": Node { - "extra": { - "raw": "'render'", - "rawValue": "render", - }, - "type": "StringLiteral", - "value": "render", - }, - "kind": "method", - "params": [], - "static": false, - "type": "ClassMethod", -} -`; - -exports[`getClassMemberValuePath > ClassExpression > finds "normal" method definitions 1`] = ` -Node { - "async": false, - "body": Node { - "body": [], - "directives": [], - "type": "BlockStatement", - }, - "computed": false, - "generator": false, - "id": null, - "key": Node { - "name": "render", - "type": "Identifier", - }, - "kind": "method", - "params": [], - "static": false, - "type": "ClassMethod", -} -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/getFlowType-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/getFlowType-test.ts.snap deleted file mode 100644 index 357ab986299..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/getFlowType-test.ts.snap +++ /dev/null @@ -1,222 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`getFlowType > detects object types with descriptions 1`] = ` -{ - "name": "signature", - "raw": "{ - /** A */ - a: string, - /** B */ - b?: xyz -}", - "signature": { - "properties": [ - { - "description": "A", - "key": "a", - "value": { - "name": "string", - "required": true, - }, - }, - { - "description": "B", - "key": "b", - "value": { - "name": "xyz", - "required": false, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getFlowType > detects object types with maybe type 1`] = ` -{ - "name": "signature", - "raw": "{ a: string, b: ?xyz }", - "signature": { - "properties": [ - { - "key": "a", - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "b", - "value": { - "name": "xyz", - "nullable": true, - "required": true, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getFlowType > handles ObjectTypeSpreadProperty 1`] = ` -{ - "name": "signature", - "raw": "{| apple: string, banana: string, ...OtherFruits |}", - "signature": { - "properties": [ - { - "key": "apple", - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "banana", - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "orange", - "value": { - "name": "string", - "required": true, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getFlowType > handles ObjectTypeSpreadProperty from imported types 1`] = ` -{ - "name": "signature", - "raw": "{| apple: string, banana: string, ...MyType |}", - "signature": { - "properties": [ - { - "key": "apple", - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "banana", - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "a", - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "b", - "value": { - "name": "notImported", - "nullable": true, - "required": true, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getFlowType > handles indexed access on alias 1`] = ` -{ - "name": "string", - "raw": "A["x"]", -} -`; - -exports[`getFlowType > handles indexed access on interface 1`] = ` -{ - "name": "A["x"]", - "raw": "A["x"]", -} -`; - -exports[`getFlowType > handles nested ObjectTypeSpreadProperty 1`] = ` -{ - "name": "signature", - "raw": "{| apple: string, banana: string, ...BreakfastFruits |}", - "signature": { - "properties": [ - { - "key": "apple", - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "banana", - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "mango", - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "orange", - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "lemon", - "value": { - "name": "string", - "required": true, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getFlowType > handles unresolved ObjectTypeSpreadProperty 1`] = ` -{ - "name": "signature", - "raw": "{| apple: string, banana: string, ...MyType |}", - "signature": { - "properties": [ - { - "key": "apple", - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "banana", - "value": { - "name": "string", - "required": true, - }, - }, - ], - }, - "type": "object", -} -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/getMemberExpressionRoot-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/getMemberExpressionRoot-test.ts.snap deleted file mode 100644 index a70ae336565..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/getMemberExpressionRoot-test.ts.snap +++ /dev/null @@ -1,32 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`getMemberExpressionRoot > returns the root of a member expression 1`] = ` -Node { - "name": "foo", - "type": "Identifier", -} -`; - -exports[`getMemberExpressionRoot > returns the same path if identifier 1`] = ` -Node { - "extra": { - "parenStart": 0, - "parenthesized": true, - }, - "name": "foo", - "type": "Identifier", -} -`; - -exports[`getMemberExpressionRoot > returns the same path if literal 1`] = ` -Node { - "extra": { - "parenStart": 0, - "parenthesized": true, - "raw": "1", - "rawValue": 1, - }, - "type": "NumericLiteral", - "value": 1, -} -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/getMembers-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/getMembers-test.ts.snap deleted file mode 100644 index 9a5bf03536e..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/getMembers-test.ts.snap +++ /dev/null @@ -1,173 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`getMembers > does work with custom expressions in arguments 1`] = ` -[ - { - "argumentPaths": [ - Node { - "left": Node { - "extra": { - "raw": "123", - "rawValue": 123, - }, - "type": "NumericLiteral", - "value": 123, - }, - "operator": "+", - "right": Node { - "extra": { - "raw": "123", - "rawValue": 123, - }, - "type": "NumericLiteral", - "value": 123, - }, - "type": "BinaryExpression", - }, - ], - "computed": false, - "path": Node { - "name": "bar", - "type": "Identifier", - }, - }, - { - "argumentPaths": [], - "computed": true, - "path": Node { - "extra": { - "raw": ""baz"", - "rawValue": "baz", - }, - "type": "StringLiteral", - "value": "baz", - }, - }, -] -`; - -exports[`getMembers > does work with custom expressions in chain 1`] = ` -[ - { - "argumentPaths": [ - Node { - "extra": { - "raw": "123", - "rawValue": 123, - }, - "type": "NumericLiteral", - "value": 123, - }, - ], - "computed": false, - "path": Node { - "name": "bar", - "type": "Identifier", - }, - }, - { - "argumentPaths": [], - "computed": true, - "path": Node { - "left": Node { - "extra": { - "raw": """", - "rawValue": "", - }, - "type": "StringLiteral", - "value": "", - }, - "operator": "+", - "right": Node { - "extra": { - "raw": """", - "rawValue": "", - }, - "type": "StringLiteral", - "value": "", - }, - "type": "BinaryExpression", - }, - }, -] -`; - -exports[`getMembers > finds all "members" "inside" a MemberExpression 1`] = ` -[ - { - "argumentPaths": [ - Node { - "extra": { - "raw": "123", - "rawValue": 123, - }, - "type": "NumericLiteral", - "value": 123, - }, - ], - "computed": false, - "path": Node { - "name": "bar", - "type": "Identifier", - }, - }, - { - "argumentPaths": [], - "computed": true, - "path": Node { - "name": "baz", - "type": "Identifier", - }, - }, - { - "argumentPaths": [], - "computed": true, - "path": Node { - "extra": { - "raw": "42", - "rawValue": 42, - }, - "type": "NumericLiteral", - "value": 42, - }, - }, -] -`; - -exports[`getMembers > includes the root if option set to true 1`] = ` -[ - { - "argumentPaths": [], - "computed": false, - "path": Node { - "name": "foo", - "type": "Identifier", - }, - }, - { - "argumentPaths": [ - Node { - "extra": { - "raw": "123", - "rawValue": 123, - }, - "type": "NumericLiteral", - "value": 123, - }, - ], - "computed": false, - "path": Node { - "name": "bar", - "type": "Identifier", - }, - }, - { - "argumentPaths": [], - "computed": true, - "path": Node { - "name": "baz", - "type": "Identifier", - }, - }, -] -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/getMethodDocumentation-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/getMethodDocumentation-test.ts.snap deleted file mode 100644 index 9cf95326ef7..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/getMethodDocumentation-test.ts.snap +++ /dev/null @@ -1,114 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`getMethodDocumentation > name > handles computed method name 1`] = ` -{ - "docblock": null, - "modifiers": [], - "name": "@computed#foo", - "params": [], - "returns": null, -} -`; - -exports[`getMethodDocumentation > name > ignores complex computed method name 1`] = `null`; - -exports[`getMethodDocumentation > parameters > does not add type parameters to alias 1`] = ` -{ - "docblock": null, - "modifiers": [], - "name": "foo", - "params": [ - { - "name": "bar", - "optional": false, - "type": { - "alias": "Foo", - "elements": [ - { - "name": "T", - }, - ], - "name": "Foo", - "raw": "Foo", - }, - }, - ], - "returns": null, -} -`; - -exports[`getMethodDocumentation > parameters > extracts flow type info 1`] = ` -{ - "docblock": null, - "modifiers": [], - "name": "foo", - "params": [ - { - "name": "bar", - "optional": false, - "type": { - "name": "number", - }, - }, - ], - "returns": null, -} -`; - -exports[`getMethodDocumentation > parameters > extracts flow type info 2`] = ` -{ - "docblock": null, - "modifiers": [], - "name": "foo", - "params": [ - { - "name": "bar", - "optional": false, - "type": { - "name": "number", - }, - }, - ], - "returns": null, -} -`; - -exports[`getMethodDocumentation > parameters > extracts flow type info on function assignment 1`] = ` -{ - "docblock": null, - "modifiers": [], - "name": "foo", - "params": [ - { - "name": "bar", - "optional": false, - "type": { - "name": "number", - }, - }, - ], - "returns": null, -} -`; - -exports[`getMethodDocumentation > parameters > private > ignores private methods 1`] = `null`; - -exports[`getMethodDocumentation > parameters > private > ignores private typescript methods 1`] = `null`; - -exports[`getMethodDocumentation > parameters > resolves flow type info on imported functions 1`] = ` -{ - "docblock": null, - "modifiers": [], - "name": "foo", - "params": [ - { - "name": "bar", - "optional": false, - "type": { - "name": "number", - }, - }, - ], - "returns": null, -} -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/getNameOrValue-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/getNameOrValue-test.ts.snap deleted file mode 100644 index df6ed0c6ea6..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/getNameOrValue-test.ts.snap +++ /dev/null @@ -1,19 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`getNameOrValue > errors on invalid path 1`] = `[TypeError: Argument must be Identifier, Literal, QualifiedTypeIdentifier or TSQualifiedName. Received 'FunctionDeclaration']`; - -exports[`getNameOrValue > gets Identifier name 1`] = `"foo"`; - -exports[`getNameOrValue > gets QualifiedTypeIdentifier 1`] = `"x.h"`; - -exports[`getNameOrValue > gets TSQualifiedName 1`] = `"x.h"`; - -exports[`getNameOrValue > gets boolean literal value 1`] = `true`; - -exports[`getNameOrValue > gets null RegExp pattern 1`] = `"abc?"`; - -exports[`getNameOrValue > gets null literal value 1`] = `null`; - -exports[`getNameOrValue > gets numeric literal value 1`] = `1`; - -exports[`getNameOrValue > gets string literal value 1`] = `"foo"`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/getPropType-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/getPropType-test.ts.snap deleted file mode 100644 index e90f2b88693..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/getPropType-test.ts.snap +++ /dev/null @@ -1,463 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`getPropType > detects custom validation functions for arrow function 1`] = ` -{ - "name": "custom", - "raw": "() => {}", -} -`; - -exports[`getPropType > detects custom validation functions for function 1`] = ` -{ - "name": "custom", - "raw": "function() {}", -} -`; - -exports[`getPropType > detects descriptions on nested types in arrayOf 1`] = ` -{ - "description": "test2", - "name": "arrayOf", - "value": { - "name": "string", - }, -} -`; - -exports[`getPropType > detects descriptions on nested types in exacts 1`] = ` -{ - "name": "exact", - "value": { - "bar": { - "description": "test2", - "name": "bool", - "required": false, - }, - "foo": { - "description": "test1", - "name": "string", - "required": false, - }, - }, -} -`; - -exports[`getPropType > detects descriptions on nested types in objectOf 1`] = ` -{ - "description": "test2", - "name": "objectOf", - "value": { - "name": "string", - }, -} -`; - -exports[`getPropType > detects descriptions on nested types in shapes 1`] = ` -{ - "name": "shape", - "value": { - "bar": { - "description": "test2", - "name": "bool", - "required": false, - }, - "foo": { - "description": "test1", - "name": "string", - "required": false, - }, - }, -} -`; - -exports[`getPropType > detects required notations of nested types in exacts 1`] = ` -{ - "name": "exact", - "value": { - "bar": { - "name": "bool", - "required": false, - }, - "foo": { - "name": "string", - "required": true, - }, - }, -} -`; - -exports[`getPropType > detects required notations of nested types in shapes 1`] = ` -{ - "name": "shape", - "value": { - "bar": { - "name": "bool", - "required": false, - }, - "foo": { - "name": "string", - "required": true, - }, - }, -} -`; - -exports[`getPropType > handles computed properties 1`] = ` -{ - "name": "exact", - "value": { - "@computed#foo": { - "name": "string", - "required": true, - }, - "bar": { - "name": "bool", - "required": false, - }, - }, -} -`; - -exports[`getPropType > ignores complex computed properties 1`] = ` -{ - "name": "exact", - "value": { - "bar": { - "name": "bool", - "required": false, - }, - }, -} -`; - -exports[`getPropType > resolve identifier to their values > correctly resolves SpreadElements in arrays 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": false, - "value": ""foo"", - }, - { - "computed": false, - "value": ""bar"", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > correctly resolves SpreadElements in arrays from imported values 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": false, - "value": ""foo"", - }, - { - "computed": false, - "value": ""bar"", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > correctly resolves nested SpreadElements in arrays 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": false, - "value": ""foo"", - }, - { - "computed": false, - "value": ""bar"", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > does not resolve external values without proper importer 1`] = ` -{ - "computed": true, - "name": "enum", - "value": "TYPES", -} -`; - -exports[`getPropType > resolve identifier to their values > does resolve object keys values 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": false, - "value": ""FOO"", - }, - { - "computed": false, - "value": ""BAR"", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > does resolve object values 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": false, - "value": ""foo"", - }, - { - "computed": false, - "value": ""bar"", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > handles unresolved imported identifier to their initialization value in array 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": true, - "value": "FOO", - }, - { - "computed": true, - "value": "BAR", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > handles unresolved named imported identifier to their initialization value in array 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": true, - "value": "FOO", - }, - { - "computed": true, - "value": "BAR", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > handles unresolved value constants from imported objects 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": false, - "value": "null", - }, - { - "computed": false, - "value": "null", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > resolves imported identifier to their initialization value in array 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": false, - "value": ""foo"", - }, - { - "computed": false, - "value": ""bar"", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > resolves imported variables to their values 1`] = ` -{ - "name": "shape", - "value": { - "bar": { - "name": "string", - "required": false, - }, - }, -} -`; - -exports[`getPropType > resolve identifier to their values > resolves importer identifier to initialization value 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": false, - "value": ""foo"", - }, - { - "computed": false, - "value": ""bar"", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > resolves memberExpressions 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": false, - "value": ""foo"", - }, - { - "computed": false, - "value": ""bar"", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > resolves memberExpressions from imported objects 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": false, - "value": ""foo"", - }, - { - "computed": false, - "value": ""bar"", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > resolves simple identifier to their initialization value 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": false, - "value": ""foo"", - }, - { - "computed": false, - "value": ""bar"", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > resolves simple identifier to their initialization value in array 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": false, - "value": ""foo"", - }, - { - "computed": false, - "value": ""bar"", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > resolves value constants from imported objects 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": false, - "value": ""foo"", - }, - { - "computed": false, - "value": ""bar"", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > resolves values from imported Object.keys call 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": false, - "value": ""FOO"", - }, - { - "computed": false, - "value": ""BAR"", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > resolves values from imported Object.values call 1`] = ` -{ - "name": "enum", - "value": [ - { - "computed": false, - "value": ""foo"", - }, - { - "computed": false, - "value": ""bar"", - }, - ], -} -`; - -exports[`getPropType > resolve identifier to their values > resolves variables to their values 1`] = ` -{ - "name": "shape", - "value": { - "bar": { - "name": "string", - "required": false, - }, - }, -} -`; - -exports[`getPropType > works with cyclic references in shape 1`] = ` -{ - "name": "shape", - "value": "Component.propTypes", -} -`; - -exports[`getPropType > works with cyclic references in shape and required 1`] = ` -{ - "name": "shape", - "value": "Component.propTypes", -} -`; - -exports[`getPropType > works with missing argument 1`] = ` -{ - "name": "shape", - "value": { - "foo": { - "computed": true, - "name": "shape", - "required": false, - "value": "", - }, - }, -} -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/getTSType-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/getTSType-test.ts.snap deleted file mode 100644 index 2d8bade52e9..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/getTSType-test.ts.snap +++ /dev/null @@ -1,1476 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`getTSType > React types > React.ChildrenArray 1`] = ` -{ - "elements": [ - { - "name": "string", - }, - ], - "name": "ReactChildrenArray", - "raw": "React.ChildrenArray", -} -`; - -exports[`getTSType > React types > React.ComponentType 1`] = ` -{ - "elements": [ - { - "name": "signature", - "raw": "{ x: string }", - "signature": { - "properties": [ - { - "key": "x", - "value": { - "name": "string", - "required": true, - }, - }, - ], - }, - "type": "object", - }, - ], - "name": "ReactComponentType", - "raw": "React.ComponentType", -} -`; - -exports[`getTSType > React types > React.Element 1`] = ` -{ - "elements": [ - { - "name": "any", - }, - ], - "name": "ReactElement", - "raw": "React.Element", -} -`; - -exports[`getTSType > React types > React.ElementProps 1`] = ` -{ - "elements": [ - { - "name": "Component", - }, - ], - "name": "ReactElementProps", - "raw": "React.ElementProps", -} -`; - -exports[`getTSType > React types > React.ElementRef 1`] = ` -{ - "elements": [ - { - "name": "Component", - }, - ], - "name": "ReactElementRef", - "raw": "React.ElementRef", -} -`; - -exports[`getTSType > React types > React.ElementType 1`] = ` -{ - "name": "ReactElementType", - "raw": "React.ElementType", -} -`; - -exports[`getTSType > React types > React.Key 1`] = ` -{ - "name": "ReactKey", - "raw": "React.Key", -} -`; - -exports[`getTSType > React types > React.Node 1`] = ` -{ - "name": "ReactNode", - "raw": "React.Node", -} -`; - -exports[`getTSType > React types > React.Ref 1`] = ` -{ - "elements": [ - { - "name": "Component", - }, - ], - "name": "ReactRef", - "raw": "React.Ref", -} -`; - -exports[`getTSType > React types > React.StatelessFunctionalComponent 1`] = ` -{ - "elements": [ - { - "name": "Props2", - }, - ], - "name": "ReactStatelessFunctionalComponent", - "raw": "React.StatelessFunctionalComponent", -} -`; - -exports[`getTSType > can resolve indexed access to imported type 1`] = ` -{ - "name": "string", - "raw": "A["x"]", -} -`; - -exports[`getTSType > detects array type 1`] = ` -{ - "elements": [ - { - "name": "number", - }, - ], - "name": "Array", - "raw": "Array", -} -`; - -exports[`getTSType > detects array type shorthand 1`] = ` -{ - "elements": [ - { - "name": "number", - }, - ], - "name": "Array", - "raw": "number[]", -} -`; - -exports[`getTSType > detects array type with multiple types 1`] = ` -{ - "elements": [ - { - "name": "number", - }, - { - "name": "xyz", - }, - ], - "name": "Array", - "raw": "Array", -} -`; - -exports[`getTSType > detects callable signature type 1`] = ` -{ - "name": "signature", - "raw": "{ (str: string): string, token: string }", - "signature": { - "constructor": { - "name": "signature", - "raw": "(str: string): string", - "signature": { - "arguments": [ - { - "name": "str", - "type": { - "name": "string", - }, - }, - ], - "return": { - "name": "string", - }, - }, - "type": "function", - }, - "properties": [ - { - "key": "token", - "value": { - "name": "string", - "required": true, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > detects class type 1`] = ` -{ - "elements": [ - { - "name": "Boolean", - }, - ], - "name": "Class", - "raw": "Class", -} -`; - -exports[`getTSType > detects external type 1`] = ` -{ - "name": "xyz", -} -`; - -exports[`getTSType > detects function signature type 1`] = ` -{ - "name": "signature", - "raw": "(p1: number, p2: string, ...rest: Array) => boolean", - "signature": { - "arguments": [ - { - "name": "p1", - "type": { - "name": "number", - }, - }, - { - "name": "p2", - "type": { - "name": "string", - }, - }, - { - "name": "rest", - "rest": true, - "type": { - "elements": [ - { - "name": "string", - }, - ], - "name": "Array", - "raw": "Array", - }, - }, - ], - "return": { - "name": "boolean", - }, - }, - "type": "function", -} -`; - -exports[`getTSType > detects function signature type with \`this\` parameter 1`] = ` -{ - "name": "signature", - "raw": "(this: Foo, p1: number) => boolean", - "signature": { - "arguments": [ - { - "name": "p1", - "type": { - "name": "number", - }, - }, - ], - "return": { - "name": "boolean", - }, - "this": { - "name": "Foo", - }, - }, - "type": "function", -} -`; - -exports[`getTSType > detects function signature type with object and array pattern 1`] = ` -{ - "name": "signature", - "raw": "({ x }: { x: number }, [ f,s ]: Array) => boolean", - "signature": { - "arguments": [ - { - "name": "", - "type": { - "name": "signature", - "raw": "{ x: number }", - "signature": { - "properties": [ - { - "key": "x", - "value": { - "name": "number", - "required": true, - }, - }, - ], - }, - "type": "object", - }, - }, - { - "name": "", - "type": { - "elements": [ - { - "name": "string", - }, - ], - "name": "Array", - "raw": "Array", - }, - }, - ], - "return": { - "name": "boolean", - }, - }, - "type": "function", -} -`; - -exports[`getTSType > detects function type with subtype 1`] = ` -{ - "elements": [ - { - "name": "xyz", - }, - ], - "name": "Function", - "raw": "Function", -} -`; - -exports[`getTSType > detects indexed access 1`] = ` -{ - "name": "A["x"]", - "raw": "A["x"]", -} -`; - -exports[`getTSType > detects intersection type 1`] = ` -{ - "elements": [ - { - "name": "string", - }, - { - "name": "xyz", - }, - { - "name": "literal", - "value": ""foo"", - }, - { - "name": "void", - }, - ], - "name": "intersection", - "raw": "string & xyz & "foo" & void", -} -`; - -exports[`getTSType > detects map signature 1`] = ` -{ - "name": "signature", - "raw": "{ [key: string]: number, [key: "xl"]: string, token: "a" | "b" }", - "signature": { - "properties": [ - { - "key": { - "name": "string", - }, - "value": { - "name": "number", - "required": true, - }, - }, - { - "key": { - "name": "literal", - "value": ""xl"", - }, - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "token", - "value": { - "elements": [ - { - "name": "literal", - "value": ""a"", - }, - { - "name": "literal", - "value": ""b"", - }, - ], - "name": "union", - "raw": ""a" | "b"", - "required": true, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > detects object types 1`] = ` -{ - "name": "signature", - "raw": "{ a: string, b?: xyz }", - "signature": { - "properties": [ - { - "key": "a", - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "b", - "value": { - "name": "xyz", - "required": false, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > detects simple types 1`] = ` -{ - "name": "string", -} -`; - -exports[`getTSType > detects simple types 2`] = ` -{ - "name": "number", -} -`; - -exports[`getTSType > detects simple types 3`] = ` -{ - "name": "boolean", -} -`; - -exports[`getTSType > detects simple types 4`] = ` -{ - "name": "symbol", -} -`; - -exports[`getTSType > detects simple types 5`] = ` -{ - "name": "object", -} -`; - -exports[`getTSType > detects simple types 6`] = ` -{ - "name": "any", -} -`; - -exports[`getTSType > detects simple types 7`] = ` -{ - "name": "unknown", -} -`; - -exports[`getTSType > detects simple types 8`] = ` -{ - "name": "null", -} -`; - -exports[`getTSType > detects simple types 9`] = ` -{ - "name": "undefined", -} -`; - -exports[`getTSType > detects simple types 10`] = ` -{ - "name": "void", -} -`; - -exports[`getTSType > detects simple types 11`] = ` -{ - "name": "Object", -} -`; - -exports[`getTSType > detects simple types 12`] = ` -{ - "name": "Function", -} -`; - -exports[`getTSType > detects simple types 13`] = ` -{ - "name": "Boolean", -} -`; - -exports[`getTSType > detects simple types 14`] = ` -{ - "name": "String", -} -`; - -exports[`getTSType > detects simple types 15`] = ` -{ - "name": "Number", -} -`; - -exports[`getTSType > detects tuple in union signature 1`] = ` -{ - "elements": [ - { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "tuple", - "raw": "[string, number]", - }, - { - "elements": [ - { - "name": "number", - }, - { - "name": "string", - }, - ], - "name": "tuple", - "raw": "[number, string]", - }, - ], - "name": "union", - "raw": "[string, number] | [number, string]", -} -`; - -exports[`getTSType > detects tuple signature 1`] = ` -{ - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "tuple", - "raw": "[string, number]", -} -`; - -exports[`getTSType > detects union type 1`] = ` -{ - "elements": [ - { - "name": "string", - }, - { - "name": "xyz", - }, - { - "name": "literal", - "value": ""foo"", - }, - { - "name": "void", - }, - ], - "name": "union", - "raw": "string | xyz | "foo" | void", -} -`; - -exports[`getTSType > handles generic types 1`] = ` -{ - "name": "signature", - "raw": "{ a: T, b: Array }", - "signature": { - "properties": [ - { - "key": "a", - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "b", - "value": { - "elements": [ - { - "name": "string", - }, - ], - "name": "Array", - "raw": "Array", - "required": true, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > handles generics of the same Name 1`] = ` -{ - "elements": [ - { - "name": "T", - }, - ], - "name": "Bar", - "raw": "Bar", -} -`; - -exports[`getTSType > handles long type cycles 1`] = ` -{ - "name": "signature", - "raw": "{ subAction: SubAction }", - "signature": { - "properties": [ - { - "key": "subAction", - "value": { - "name": "signature", - "raw": "{ subAction: SubSubAction }", - "required": true, - "signature": { - "properties": [ - { - "key": "subAction", - "value": { - "name": "signature", - "raw": "{ subAction: SubSubSubAction }", - "required": true, - "signature": { - "properties": [ - { - "key": "subAction", - "value": { - "name": "signature", - "raw": "{ rootAction: Action }", - "required": true, - "signature": { - "properties": [ - { - "key": "rootAction", - "value": { - "name": "Action", - "required": true, - }, - }, - ], - }, - "type": "object", - }, - }, - ], - }, - "type": "object", - }, - }, - ], - }, - "type": "object", - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > handles mapped type 1`] = ` -{ - "name": "signature", - "raw": "{ - [Property in keyof Type]: number; -}", - "signature": { - "properties": [ - { - "key": { - "name": "X", - "required": true, - }, - "value": { - "name": "number", - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > handles mapped type with implicit any 1`] = ` -{ - "name": "signature", - "raw": "{ - [Property in keyof Type]; -}", - "signature": { - "properties": [ - { - "key": { - "name": "X", - "required": true, - }, - "value": { - "name": "any", - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > handles mapped type without typeParam 1`] = ` -{ - "name": "signature", - "raw": "{ - [Property in keyof X]: string; -}", - "signature": { - "properties": [ - { - "key": { - "name": "X", - "required": true, - }, - "value": { - "name": "string", - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > handles mapped types 1`] = ` -{ - "name": "signature", - "raw": "{ [key in 'x' | 'y']: boolean}", - "signature": { - "properties": [ - { - "key": { - "elements": [ - { - "name": "literal", - "value": "'x'", - }, - { - "name": "literal", - "value": "'y'", - }, - ], - "name": "union", - "raw": "'x' | 'y'", - "required": true, - }, - "value": { - "name": "boolean", - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > handles multiple references to one type 1`] = ` -{ - "name": "signature", - "raw": "{ a: Action, b: Action }", - "signature": { - "properties": [ - { - "key": "a", - "value": { - "name": "signature", - "raw": "{}", - "required": true, - "signature": { - "properties": [], - }, - "type": "object", - }, - }, - { - "key": "b", - "value": { - "name": "signature", - "raw": "{}", - "required": true, - "signature": { - "properties": [], - }, - "type": "object", - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > handles qualified type identifiers 1`] = ` -{ - "name": "MyType.x", -} -`; - -exports[`getTSType > handles qualified type identifiers with params 1`] = ` -{ - "elements": [ - { - "name": "any", - }, - ], - "name": "MyType.x", - "raw": "MyType.x", -} -`; - -exports[`getTSType > handles self-referencing type cycles 1`] = ` -{ - "name": "signature", - "raw": "{ subAction: Action }", - "signature": { - "properties": [ - { - "key": "subAction", - "value": { - "name": "Action", - "required": true, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > handles typeof qualified type 1`] = ` -{ - "name": "MyType.a", -} -`; - -exports[`getTSType > handles typeof type 1`] = ` -{ - "name": "signature", - "raw": "{ a: string, b: xyz }", - "signature": { - "properties": [ - { - "key": "a", - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "b", - "value": { - "name": "xyz", - "required": true, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > literal types > detects "foo" 1`] = ` -{ - "name": "literal", - "value": ""foo"", -} -`; - -exports[`getTSType > literal types > detects \`foo\` 1`] = ` -{ - "name": "literal", - "value": "\`foo\`", -} -`; - -exports[`getTSType > literal types > detects -1 1`] = ` -{ - "name": "literal", - "value": "-1", -} -`; - -exports[`getTSType > literal types > detects 1234 1`] = ` -{ - "name": "literal", - "value": "1234", -} -`; - -exports[`getTSType > literal types > detects true 1`] = ` -{ - "name": "literal", - "value": "true", -} -`; - -exports[`getTSType > resolves external type 1`] = ` -{ - "name": "string", -} -`; - -exports[`getTSType > resolves function signature types with imported types 1`] = ` -{ - "name": "signature", - "raw": "(p1: abc, p2: xyz, ...rest: Array) => def", - "signature": { - "arguments": [ - { - "name": "p1", - "type": { - "name": "number", - }, - }, - { - "name": "p2", - "type": { - "name": "string", - }, - }, - { - "name": "rest", - "rest": true, - "type": { - "elements": [ - { - "name": "string", - }, - ], - "name": "Array", - "raw": "Array", - }, - }, - ], - "return": { - "name": "boolean", - }, - }, - "type": "function", -} -`; - -exports[`getTSType > resolves function signature types with imported types 2`] = ` -{ - "name": "signature", - "raw": "(this: xyz, p1: number) => boolean", - "signature": { - "arguments": [ - { - "name": "p1", - "type": { - "name": "number", - }, - }, - ], - "return": { - "name": "boolean", - }, - "this": { - "name": "string", - }, - }, - "type": "function", -} -`; - -exports[`getTSType > resolves function signature types with imported types 3`] = ` -{ - "name": "signature", - "raw": "{ (str: xyz): abc, token: def }", - "signature": { - "constructor": { - "name": "signature", - "raw": "(str: xyz): abc", - "signature": { - "arguments": [ - { - "name": "str", - "type": { - "name": "string", - }, - }, - ], - "return": { - "name": "number", - }, - }, - "type": "function", - }, - "properties": [ - { - "key": "token", - "value": { - "name": "boolean", - "required": true, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > resolves imported subtype for class type 1`] = ` -{ - "elements": [ - { - "name": "string", - }, - ], - "name": "Class", - "raw": "Class", -} -`; - -exports[`getTSType > resolves imported subtype for function type 1`] = ` -{ - "elements": [ - { - "name": "string", - }, - ], - "name": "Function", - "raw": "Function", -} -`; - -exports[`getTSType > resolves imported types applied to mapped types 1`] = ` -{ - "name": "signature", - "raw": "{ [key in barbaz]: boolean}", - "signature": { - "properties": [ - { - "key": { - "elements": [ - { - "name": "literal", - "value": ""bar"", - }, - { - "name": "literal", - "value": ""baz"", - }, - ], - "name": "union", - "raw": ""bar" | "baz"", - "required": true, - }, - "value": { - "name": "boolean", - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > resolves imported types for object property types 1`] = ` -{ - "name": "signature", - "raw": "{ a: number, b?: xyz }", - "signature": { - "properties": [ - { - "key": "a", - "value": { - "name": "number", - "required": true, - }, - }, - { - "key": "b", - "value": { - "name": "string", - "required": false, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > resolves imported types in map signature 1`] = ` -{ - "name": "signature", - "raw": "{ [key: xyz]: abc, [key: "xl"]: xyz, token: barbaz }", - "signature": { - "properties": [ - { - "key": { - "name": "string", - "required": true, - }, - "value": { - "name": "number", - "required": true, - }, - }, - { - "key": { - "name": "literal", - "value": ""xl"", - }, - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "token", - "value": { - "elements": [ - { - "name": "literal", - "value": ""bar"", - }, - { - "name": "literal", - "value": ""baz"", - }, - ], - "name": "union", - "raw": ""bar" | "baz"", - "required": true, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > resolves imported types in tuple signatures 1`] = ` -{ - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "tuple", - "raw": "[xyz, abc]", -} -`; - -exports[`getTSType > resolves imported types in tuple signatures 2`] = ` -{ - "elements": [ - { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "tuple", - "raw": "[xyz, abc]", - }, - { - "elements": [ - { - "name": "number", - }, - { - "name": "string", - }, - ], - "name": "tuple", - "raw": "[abc, xyz]", - }, - ], - "name": "union", - "raw": "[xyz, abc] | recTup", -} -`; - -exports[`getTSType > resolves imported types that need subtypes 1`] = ` -{ - "name": "signature", - "raw": "{ a: T, b: Array }", - "signature": { - "properties": [ - { - "key": "a", - "value": { - "name": "string", - "required": true, - }, - }, - { - "key": "b", - "value": { - "elements": [ - { - "name": "string", - }, - ], - "name": "Array", - "raw": "Array", - "required": true, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > resolves imported types used for arrays 1`] = ` -{ - "elements": [ - { - "name": "string", - }, - ], - "name": "Array", - "raw": "xyz[]", -} -`; - -exports[`getTSType > resolves imported types used for arrays 2`] = ` -{ - "elements": [ - { - "name": "string", - }, - ], - "name": "Array", - "raw": "Array", -} -`; - -exports[`getTSType > resolves imported types used for arrays 3`] = ` -{ - "elements": [ - { - "name": "number", - }, - { - "name": "string", - }, - ], - "name": "Array", - "raw": "Array", -} -`; - -exports[`getTSType > resolves imported types within intersection type 1`] = ` -{ - "elements": [ - { - "name": "string", - }, - { - "elements": [ - { - "name": "literal", - "value": ""bar"", - }, - { - "name": "literal", - "value": ""baz"", - }, - ], - "name": "union", - "raw": ""bar" | "baz"", - }, - { - "name": "literal", - "value": ""foo"", - }, - { - "name": "void", - }, - ], - "name": "intersection", - "raw": "string & barbaz & "foo" & void", -} -`; - -exports[`getTSType > resolves imported types within union type 1`] = ` -{ - "elements": [ - { - "name": "string", - }, - { - "elements": [ - { - "name": "literal", - "value": ""bar"", - }, - { - "name": "literal", - "value": ""baz"", - }, - ], - "name": "union", - "raw": ""bar" | "baz"", - }, - { - "name": "literal", - "value": ""foo"", - }, - { - "name": "void", - }, - ], - "name": "union", - "raw": "string | barbaz | "foo" | void", -} -`; - -exports[`getTSType > resolves indexed access 1`] = ` -{ - "name": "string", - "raw": "A["x"]", -} -`; - -exports[`getTSType > resolves indexed access of array 1`] = ` -{ - "name": "STRING_VALS[number]", - "raw": "typeof STRING_VALS[number]", -} -`; - -exports[`getTSType > resolves keyof to union 1`] = ` -{ - "elements": [ - { - "name": "literal", - "value": "'apple'", - }, - { - "name": "literal", - "value": "'banana'", - }, - ], - "name": "union", - "raw": "keyof typeof CONTENTS", -} -`; - -exports[`getTSType > resolves keyof with imported types 1`] = ` -{ - "elements": [ - { - "name": "literal", - "value": "'apple'", - }, - { - "name": "literal", - "value": "'banana'", - }, - ], - "name": "union", - "raw": "keyof typeof CONTENTS", -} -`; - -exports[`getTSType > resolves keyof with inline object to union 1`] = ` -{ - "elements": [ - { - "name": "literal", - "value": "apple", - }, - { - "name": "literal", - "value": "banana", - }, - ], - "name": "union", - "raw": "keyof { apple: string, banana: string }", -} -`; - -exports[`getTSType > resolves typeof of import type 1`] = ` -{ - "name": "import('MyType')", -} -`; - -exports[`getTSType > resolves typeof of imported type 1`] = ` -{ - "name": "signature", - "raw": "{ a: number, b: xyz }", - "signature": { - "properties": [ - { - "key": "a", - "value": { - "name": "number", - "required": true, - }, - }, - { - "key": "b", - "value": { - "name": "string", - "required": true, - }, - }, - ], - }, - "type": "object", -} -`; - -exports[`getTSType > resolves types in scope 1`] = ` -{ - "name": "string", -} -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/getTypeFromReactComponent-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/getTypeFromReactComponent-test.ts.snap deleted file mode 100644 index e2a00ad3a7d..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/getTypeFromReactComponent-test.ts.snap +++ /dev/null @@ -1,289 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`getTypeFromReactComponent > Flow > classes > finds props type in new params 1`] = ` -[ - Node { - "id": Node { - "name": "Props", - "type": "Identifier", - }, - "type": "GenericTypeAnnotation", - "typeParameters": null, - }, -] -`; - -exports[`getTypeFromReactComponent > Flow > classes > finds props type in old params 1`] = ` -[ - Node { - "id": Node { - "name": "Props", - "type": "Identifier", - }, - "type": "GenericTypeAnnotation", - "typeParameters": null, - }, -] -`; - -exports[`getTypeFromReactComponent > Flow > classes > finds props type in properties 1`] = ` -[ - Node { - "id": Node { - "name": "Props", - "type": "Identifier", - }, - "type": "GenericTypeAnnotation", - "typeParameters": null, - }, -] -`; - -exports[`getTypeFromReactComponent > Flow > stateless > finds param inline type 1`] = ` -[ - Node { - "callProperties": [], - "exact": false, - "indexers": [], - "inexact": false, - "internalSlots": [], - "properties": [ - Node { - "key": Node { - "name": "prop", - "type": "Identifier", - }, - "kind": "init", - "method": false, - "optional": false, - "proto": false, - "static": false, - "type": "ObjectTypeProperty", - "value": Node { - "type": "StringTypeAnnotation", - }, - "variance": null, - }, - ], - "type": "ObjectTypeAnnotation", - }, -] -`; - -exports[`getTypeFromReactComponent > Flow > stateless > finds param type annotation 1`] = ` -[ - Node { - "id": Node { - "name": "Props", - "type": "Identifier", - }, - "type": "GenericTypeAnnotation", - "typeParameters": null, - }, -] -`; - -exports[`getTypeFromReactComponent > TypeScript > classes > finds props type in params 1`] = ` -[ - Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, - }, -] -`; - -exports[`getTypeFromReactComponent > TypeScript > classes > finds props type in properties 1`] = ` -[ - Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, - }, -] -`; - -exports[`getTypeFromReactComponent > TypeScript > stateless > does not find generic forwardRef type annotation on typo 1`] = `[]`; - -exports[`getTypeFromReactComponent > TypeScript > stateless > finds generic forwardRef type annotation 1`] = ` -[ - Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, - }, -] -`; - -exports[`getTypeFromReactComponent > TypeScript > stateless > finds multiple variable type annotation 1`] = ` -[ - Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, - }, - Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, - }, -] -`; - -exports[`getTypeFromReactComponent > TypeScript > stateless > finds param inline type 1`] = ` -[ - Node { - "members": [ - Node { - "computed": false, - "key": Node { - "name": "prop", - "type": "Identifier", - }, - "type": "TSPropertySignature", - "typeAnnotation": Node { - "type": "TSTypeAnnotation", - "typeAnnotation": Node { - "type": "TSStringKeyword", - }, - }, - }, - ], - "type": "TSTypeLiteral", - }, -] -`; - -exports[`getTypeFromReactComponent > TypeScript > stateless > finds param type annotation 1`] = ` -[ - Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, - }, -] -`; - -exports[`getTypeFromReactComponent > TypeScript > stateless > finds variable type annotation (FC) > with MemberExpression 1`] = ` -[ - Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, - }, -] -`; - -exports[`getTypeFromReactComponent > TypeScript > stateless > finds variable type annotation (FC) > with named import 1`] = ` -[ - Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, - }, -] -`; - -exports[`getTypeFromReactComponent > TypeScript > stateless > finds variable type annotation (FunctionComponent) > with MemberExpression 1`] = ` -[ - Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, - }, -] -`; - -exports[`getTypeFromReactComponent > TypeScript > stateless > finds variable type annotation (FunctionComponent) > with named import 1`] = ` -[ - Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, - }, -] -`; - -exports[`getTypeFromReactComponent > TypeScript > stateless > finds variable type annotation (VFC) > with MemberExpression 1`] = ` -[ - Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, - }, -] -`; - -exports[`getTypeFromReactComponent > TypeScript > stateless > finds variable type annotation (VFC) > with named import 1`] = ` -[ - Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, - }, -] -`; - -exports[`getTypeFromReactComponent > TypeScript > stateless > finds variable type annotation (VoidFunctionComponent) > with MemberExpression 1`] = ` -[ - Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, - }, -] -`; - -exports[`getTypeFromReactComponent > TypeScript > stateless > finds variable type annotation (VoidFunctionComponent) > with named import 1`] = ` -[ - Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, - }, -] -`; - -exports[`getTypeFromReactComponent > TypeScript > stateless > finds wrapped param type annotation 1`] = ` -[ - Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, - }, -] -`; - -exports[`getTypeFromReactComponent > handles no class props 1`] = `[]`; - -exports[`getTypeFromReactComponent > handles no stateless props 1`] = `[]`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/getTypeParameters-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/getTypeParameters-test.ts.snap deleted file mode 100644 index db65f7d1a2c..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/getTypeParameters-test.ts.snap +++ /dev/null @@ -1,41 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`getTypeParameters > Flow > detects simple type 1`] = ` -{ - "T": Node { - "id": Node { - "name": "T", - "type": "Identifier", - }, - "type": "GenericTypeAnnotation", - "typeParameters": null, - }, -} -`; - -exports[`getTypeParameters > TypeScript > detects default 1`] = ` -{ - "R": Node { - "type": "TSStringKeyword", - }, - "T": Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "T", - "type": "Identifier", - }, - }, -} -`; - -exports[`getTypeParameters > TypeScript > detects simple type 1`] = ` -{ - "T": Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "T", - "type": "Identifier", - }, - }, -} -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/parseJsDoc-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/parseJsDoc-test.ts.snap deleted file mode 100644 index 9adf5895dce..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/parseJsDoc-test.ts.snap +++ /dev/null @@ -1,189 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`parseJsDoc > @param > extracts jsdoc description 1`] = ` -{ - "description": null, - "params": [ - { - "description": "test", - "name": "bar", - "optional": false, - "type": null, - }, - ], - "returns": null, -} -`; - -exports[`parseJsDoc > @param > extracts jsdoc empty description 1`] = ` -{ - "description": null, - "params": [ - { - "description": null, - "name": "bar", - "optional": false, - "type": { - "name": "string", - }, - }, - ], - "returns": null, -} -`; - -exports[`parseJsDoc > @param > extracts jsdoc optional 1`] = ` -{ - "description": null, - "params": [ - { - "description": null, - "name": "bar", - "optional": true, - "type": { - "name": "string", - }, - }, - ], - "returns": null, -} -`; - -exports[`parseJsDoc > @param > extracts jsdoc typed array 1`] = ` -{ - "description": null, - "params": [ - { - "description": null, - "name": "bar", - "optional": false, - "type": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "tuple", - }, - }, - ], - "returns": null, -} -`; - -exports[`parseJsDoc > @param > extracts jsdoc union type param 1`] = ` -{ - "description": null, - "params": [ - { - "description": null, - "name": "bar", - "optional": false, - "type": { - "elements": [ - { - "name": "string", - }, - { - "name": "Object", - }, - { - "elements": [ - { - "name": "some", - }, - ], - "name": "Array", - }, - ], - "name": "union", - }, - }, - ], - "returns": null, -} -`; - -exports[`parseJsDoc > @returns > extracts description from jsdoc 1`] = ` -{ - "description": null, - "params": [], - "returns": { - "description": "The number", - "type": null, - }, -} -`; - -exports[`parseJsDoc > @returns > extracts jsdoc mixed types 1`] = ` -{ - "description": null, - "params": [], - "returns": { - "description": null, - "type": { - "name": "mixed", - }, - }, -} -`; - -exports[`parseJsDoc > @returns > extracts jsdoc typed array 1`] = ` -{ - "description": null, - "params": [ - { - "description": null, - "name": "bar", - "optional": false, - "type": { - "elements": [ - { - "name": "string", - }, - { - "name": "number", - }, - ], - "name": "tuple", - }, - }, - ], - "returns": null, -} -`; - -exports[`parseJsDoc > @returns > extracts jsdoc types 1`] = ` -{ - "description": null, - "params": [], - "returns": { - "description": null, - "type": { - "name": "string", - }, - }, -} -`; - -exports[`parseJsDoc > @returns > works with @return 1`] = ` -{ - "description": null, - "params": [], - "returns": { - "description": "The number", - "type": null, - }, -} -`; - -exports[`parseJsDoc > description > extracts the method description in jsdoc 1`] = ` -{ - "description": "Don't use this!", - "params": [], - "returns": null, -} -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/printValue-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/printValue-test.ts.snap deleted file mode 100644 index 6926d916d75..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/printValue-test.ts.snap +++ /dev/null @@ -1,27 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`printValue > deindents code 1`] = ` -"function () { - return x; -}" -`; - -exports[`printValue > removes trailing , for TsCallSignatureDeclaration 1`] = `"(): number"`; - -exports[`printValue > removes trailing , for TsConstructSignatureDeclaration 1`] = `"new (x:number)"`; - -exports[`printValue > removes trailing , for TsIndexSignature 1`] = `"[x:string]: number"`; - -exports[`printValue > removes trailing , for TsMethodSignature 1`] = `"x(): number"`; - -exports[`printValue > removes trailing , for TsPropertySignature 1`] = `"x: number"`; - -exports[`printValue > removes trailing ; for TsCallSignatureDeclaration 1`] = `"(): number"`; - -exports[`printValue > removes trailing ; for TsConstructSignatureDeclaration 1`] = `"new (x:number)"`; - -exports[`printValue > removes trailing ; for TsIndexSignature 1`] = `"[x:string]: number"`; - -exports[`printValue > removes trailing ; for TsMethodSignature 1`] = `"x(): number"`; - -exports[`printValue > removes trailing ; for TsPropertySignature 1`] = `"x: number"`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveFunctionDefinitionToReturnValue-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveFunctionDefinitionToReturnValue-test.ts.snap deleted file mode 100644 index d83d3d9cb90..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveFunctionDefinitionToReturnValue-test.ts.snap +++ /dev/null @@ -1,23 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`resolveFunctionDefinitionToReturnValue > can resolve easy return statement 1`] = ` -Node { - "extra": { - "raw": ""result"", - "rawValue": "result", - }, - "type": "StringLiteral", - "value": "result", -} -`; - -exports[`resolveFunctionDefinitionToReturnValue > stops after first return 1`] = ` -Node { - "extra": { - "raw": ""first"", - "rawValue": "first", - }, - "type": "StringLiteral", - "value": "first", -} -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveGenericTypeAnnotations-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveGenericTypeAnnotations-test.ts.snap deleted file mode 100644 index a6ae04b8ebc..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveGenericTypeAnnotations-test.ts.snap +++ /dev/null @@ -1,30 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`resolveGenericTypeAnnotation > resolves type 1`] = ` -Node { - "callProperties": [], - "exact": false, - "indexers": [], - "inexact": false, - "internalSlots": [], - "properties": [ - Node { - "key": Node { - "name": "x", - "type": "Identifier", - }, - "kind": "init", - "method": false, - "optional": false, - "proto": false, - "static": false, - "type": "ObjectTypeProperty", - "value": Node { - "type": "StringTypeAnnotation", - }, - "variance": null, - }, - ], - "type": "ObjectTypeAnnotation", -} -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveHOC-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveHOC-test.ts.snap deleted file mode 100644 index b76d87742f8..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveHOC-test.ts.snap +++ /dev/null @@ -1,96 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`resolveHOC > can resolve an hocs inside imported component passed to hoc 1`] = ` -Node { - "name": "Component", - "type": "Identifier", -} -`; - -exports[`resolveHOC > can resolve an imported component passed to hoc 1`] = ` -Node { - "name": "Component", - "type": "Identifier", -} -`; - -exports[`resolveHOC > can resolve an imported component passed to nested hoc 1`] = ` -Node { - "name": "Component", - "type": "Identifier", -} -`; - -exports[`resolveHOC > resolves HOC as last element if first is array 1`] = ` -Node { - "name": "Component", - "type": "Identifier", -} -`; - -exports[`resolveHOC > resolves HOC as last element if first is literal 1`] = ` -Node { - "name": "Component", - "type": "Identifier", -} -`; - -exports[`resolveHOC > resolves HOC as last element if first is object 1`] = ` -Node { - "name": "Component", - "type": "Identifier", -} -`; - -exports[`resolveHOC > resolves HOC as last element if first is spread 1`] = ` -Node { - "name": "Component", - "type": "Identifier", -} -`; - -exports[`resolveHOC > resolves HOC with additional params 1`] = ` -Node { - "name": "Component", - "type": "Identifier", -} -`; - -exports[`resolveHOC > resolves intermediate hocs 1`] = ` -Node { - "extra": { - "raw": "42", - "rawValue": 42, - }, - "type": "NumericLiteral", - "value": 42, -} -`; - -exports[`resolveHOC > resolves nested hocs 1`] = ` -Node { - "name": "Component", - "type": "Identifier", -} -`; - -exports[`resolveHOC > resolves really nested hocs 1`] = ` -Node { - "name": "Component", - "type": "Identifier", -} -`; - -exports[`resolveHOC > resolves simple hoc 1`] = ` -Node { - "name": "Component", - "type": "Identifier", -} -`; - -exports[`resolveHOC > resolves simple hoc w/ multiple args 1`] = ` -Node { - "name": "Component", - "type": "Identifier", -} -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveObjectKeysToArray-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveObjectKeysToArray-test.ts.snap deleted file mode 100644 index cef4d7a1ad0..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveObjectKeysToArray-test.ts.snap +++ /dev/null @@ -1,79 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`resolveObjectKeysToArray > can resolve imported objects passed to Object.keys 1`] = ` -[ - ""bar"", - ""foo"", - ""1"", - ""2"", - ""3"", - ""baz"", -] -`; - -exports[`resolveObjectKeysToArray > can resolve spreads from imported objects 1`] = ` -[ - ""foo"", - ""baz"", - ""bar"", -] -`; - -exports[`resolveObjectKeysToArray > resolves Object.keys but ignores duplicates 1`] = ` -[ - ""boo"", - ""foo"", - ""doo"", -] -`; - -exports[`resolveObjectKeysToArray > resolves Object.keys but ignores duplicates with getter and setter 1`] = ` -[ - ""x"", -] -`; - -exports[`resolveObjectKeysToArray > resolves Object.keys when using getters 1`] = ` -[ - ""boo"", - ""foo"", - ""bar"", -] -`; - -exports[`resolveObjectKeysToArray > resolves Object.keys when using resolvable spread 1`] = ` -[ - ""boo"", - ""foo"", - ""doo"", -] -`; - -exports[`resolveObjectKeysToArray > resolves Object.keys when using setters 1`] = ` -[ - ""boo"", - ""foo"", - ""bar"", -] -`; - -exports[`resolveObjectKeysToArray > resolves Object.keys with identifiers 1`] = ` -[ - ""bar"", - ""foo"", -] -`; - -exports[`resolveObjectKeysToArray > resolves Object.keys with literals 1`] = ` -[ - ""bar"", - ""5"", -] -`; - -exports[`resolveObjectKeysToArray > resolves Object.keys with literals as computed key 1`] = ` -[ - ""bar"", - ""5"", -] -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveObjectPatternPropertyToValue-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveObjectPatternPropertyToValue-test.ts.snap deleted file mode 100644 index efca17613fa..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveObjectPatternPropertyToValue-test.ts.snap +++ /dev/null @@ -1,23 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`resolveObjectPatternPropertyToValue > AssignmentExpression > resolved basic case 1`] = ` -Node { - "extra": { - "raw": ""string"", - "rawValue": "string", - }, - "type": "StringLiteral", - "value": "string", -} -`; - -exports[`resolveObjectPatternPropertyToValue > VariableDeclarator > resolved basic case 1`] = ` -Node { - "extra": { - "raw": ""string"", - "rawValue": "string", - }, - "type": "StringLiteral", - "value": "string", -} -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveObjectValuesToArray-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveObjectValuesToArray-test.ts.snap deleted file mode 100644 index cc45d72b263..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveObjectValuesToArray-test.ts.snap +++ /dev/null @@ -1,89 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`resolveObjectValuesToArray > can resolve imported objects passed to Object.values 1`] = ` -[ - ""bar"", - ""foo"", - "0", - "5", - "null", - "null", - "7", - ""foo"", -] -`; - -exports[`resolveObjectValuesToArray > can resolve spreads from imported objects 1`] = ` -[ - ""foo"", - ""baz"", - ""bar"", -] -`; - -exports[`resolveObjectValuesToArray > resolves Object.values but ignores duplicates 1`] = ` -[ - "1", - "2", - "5", -] -`; - -exports[`resolveObjectValuesToArray > resolves Object.values but ignores duplicates with getter and setter 1`] = `[]`; - -exports[`resolveObjectValuesToArray > resolves Object.values when using getters 1`] = ` -[ - "1", - "2", -] -`; - -exports[`resolveObjectValuesToArray > resolves Object.values when using methods 1`] = ` -[ - "1", - "2", -] -`; - -exports[`resolveObjectValuesToArray > resolves Object.values when using resolvable spread 1`] = ` -[ - "1", - "2", - "4", -] -`; - -exports[`resolveObjectValuesToArray > resolves Object.values when using setters 1`] = ` -[ - "1", - "2", -] -`; - -exports[`resolveObjectValuesToArray > resolves Object.values with literals as computed key 1`] = ` -[ - "1", - "2", -] -`; - -exports[`resolveObjectValuesToArray > resolves Object.values with numbers 1`] = ` -[ - "0", - "5", -] -`; - -exports[`resolveObjectValuesToArray > resolves Object.values with strings 1`] = ` -[ - ""bar"", - ""foo"", -] -`; - -exports[`resolveObjectValuesToArray > resolves Object.values with undefined or null 1`] = ` -[ - "null", - "null", -] -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveToValue-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveToValue-test.ts.snap deleted file mode 100644 index 2c835baa216..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/resolveToValue-test.ts.snap +++ /dev/null @@ -1,176 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`resolveToValue > ImportDeclaration > does not crash when resolving MemberExpression with non Identifiers 1`] = ` -Node { - "computed": true, - "object": Node { - "name": "bar", - "type": "Identifier", - }, - "property": Node { - "async": false, - "body": Node { - "body": [], - "directives": [], - "type": "BlockStatement", - }, - "generator": false, - "id": null, - "params": [], - "type": "ArrowFunctionExpression", - }, - "type": "MemberExpression", -} -`; - -exports[`resolveToValue > ImportDeclaration > resolves namespace import references to the import declaration 1`] = ` -Node { - "extra": { - "raw": "3", - "rawValue": 3, - }, - "type": "NumericLiteral", - "value": 3, -} -`; - -exports[`resolveToValue > ImportDeclaration > resolves namespace import references to the import declaration 2`] = ` -Node { - "extra": { - "raw": "3", - "rawValue": 3, - }, - "type": "NumericLiteral", - "value": 3, -} -`; - -exports[`resolveToValue > MemberExpression > resolves a MemberExpression in the scope chain 1`] = ` -Node { - "extra": { - "raw": "1", - "rawValue": 1, - }, - "type": "NumericLiteral", - "value": 1, -} -`; - -exports[`resolveToValue > MemberExpression > resolves a MemberExpression to it's init value 1`] = ` -Node { - "extra": { - "raw": "1", - "rawValue": 1, - }, - "type": "NumericLiteral", - "value": 1, -} -`; - -exports[`resolveToValue > MemberExpression > resolves a nested MemberExpression in the scope chain 1`] = ` -Node { - "extra": { - "raw": "1", - "rawValue": 1, - }, - "type": "NumericLiteral", - "value": 1, -} -`; - -exports[`resolveToValue > MemberExpression > returns the last resolvable MemberExpression 1`] = ` -Node { - "computed": false, - "object": Node { - "name": "foo", - "type": "Identifier", - }, - "property": Node { - "name": "bar", - "type": "Identifier", - }, - "type": "MemberExpression", -} -`; - -exports[`resolveToValue > assignments > resolves to assigned values 1`] = ` -Node { - "extra": { - "raw": "42", - "rawValue": 42, - }, - "type": "NumericLiteral", - "value": 42, -} -`; - -exports[`resolveToValue > assignments > resolves to other assigned value if ref is in an assignment lhs 1`] = ` -Node { - "extra": { - "raw": "42", - "rawValue": 42, - }, - "type": "NumericLiteral", - "value": 42, -} -`; - -exports[`resolveToValue > assignments > resolves to other assigned value if ref is in an assignment rhs 1`] = ` -Node { - "extra": { - "raw": "42", - "rawValue": 42, - }, - "type": "NumericLiteral", - "value": 42, -} -`; - -exports[`resolveToValue > handles RestElements properly 1`] = ` -Node { - "argument": Node { - "name": "baz", - "type": "Identifier", - }, - "type": "RestElement", -} -`; - -exports[`resolveToValue > resolves object destructuring 1`] = ` -Node { - "computed": false, - "key": Node { - "name": "bar", - "type": "Identifier", - }, - "method": false, - "shorthand": false, - "type": "ObjectProperty", - "value": Node { - "name": "baz", - "type": "Identifier", - }, -} -`; - -exports[`resolveToValue > resolves simple variable declarations 1`] = ` -Node { - "extra": { - "raw": "42", - "rawValue": 42, - }, - "type": "NumericLiteral", - "value": 42, -} -`; - -exports[`resolveToValue > resolves variable declarators to their init value 1`] = ` -Node { - "extra": { - "raw": "42", - "rawValue": 42, - }, - "type": "NumericLiteral", - "value": 42, -} -`; diff --git a/packages/react-docgen/src/utils/__tests__/__snapshots__/unwrapBuiltinTSPropTypes-test.ts.snap b/packages/react-docgen/src/utils/__tests__/__snapshots__/unwrapBuiltinTSPropTypes-test.ts.snap deleted file mode 100644 index ac938cafe2b..00000000000 --- a/packages/react-docgen/src/utils/__tests__/__snapshots__/unwrapBuiltinTSPropTypes-test.ts.snap +++ /dev/null @@ -1,71 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`unwrapBuiltinTSPropTypes > React.PropsWithChildren 1`] = ` -Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, -} -`; - -exports[`unwrapBuiltinTSPropTypes > React.PropsWithRef 1`] = ` -Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, -} -`; - -exports[`unwrapBuiltinTSPropTypes > React.PropsWithoutRef 1`] = ` -Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, -} -`; - -exports[`unwrapBuiltinTSPropTypes > does not follow reassignment 1`] = ` -Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "bar", - "type": "Identifier", - }, -} -`; - -exports[`unwrapBuiltinTSPropTypes > multiple 1`] = ` -Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, -} -`; - -exports[`unwrapBuiltinTSPropTypes > with named import 1`] = ` -Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, -} -`; - -exports[`unwrapBuiltinTSPropTypes > with require 1`] = ` -Node { - "type": "TSTypeReference", - "typeName": Node { - "name": "Props", - "type": "Identifier", - }, -} -`; diff --git a/packages/react-docgen/src/utils/__tests__/docblock-test.ts b/packages/react-docgen/src/utils/__tests__/docblock-test.ts deleted file mode 100644 index e56e59fb03e..00000000000 --- a/packages/react-docgen/src/utils/__tests__/docblock-test.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { parse } from '../../../tests/utils'; -import { getDoclets, getDocblock } from '../docblock.js'; -import { describe, expect, test } from 'vitest'; - -describe('docblock', () => { - describe('getDoclets', () => { - test('extracts single line doclets', () => { - expect(getDoclets('@foo bar\n@bar baz')).toEqual({ - foo: 'bar', - bar: 'baz', - }); - }); - - test('extracts multi line doclets', () => { - expect(getDoclets('@foo bar\nbaz\n@bar baz')).toEqual({ - foo: 'bar\nbaz', - bar: 'baz', - }); - }); - - test('extracts boolean doclets', () => { - expect(getDoclets('@foo bar\nbaz\n@abc\n@bar baz')).toEqual({ - foo: 'bar\nbaz', - abc: true, - bar: 'baz', - }); - }); - }); - - describe('getDocblock', () => { - const comment = ['This is a docblock.', 'This is the second line.']; - const source = [ - '/**', - ` * ${comment[0]}`, - ` * ${comment[1]}`, - ' */', - 'foo;', - ]; - - test('gets the closest docblock of the given node', () => { - const node = parse.statement(source.join('\n')); - - expect(getDocblock(node)).toEqual(comment.join('\n')); - }); - - const terminators = [ - '\u000A', // \n - '\u000D', // \r - '\u2028', - '\u2029', - '\u000D\u000A', // \r\n - ]; - - terminators.forEach((t) => { - test('can handle ' + escape(t) + ' as line terminator', () => { - const node = parse.statement(source.join(t)); - - expect(getDocblock(node)).toEqual(comment.join(t)); - }); - }); - - test('supports "short" docblocks', () => { - const node = parse.statement('/** bar */\nfoo;'); - - expect(getDocblock(node)).toEqual('bar'); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/expressionTo-test.ts b/packages/react-docgen/src/utils/__tests__/expressionTo-test.ts deleted file mode 100644 index 11635244930..00000000000 --- a/packages/react-docgen/src/utils/__tests__/expressionTo-test.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { parse, parseTypescript } from '../../../tests/utils'; -import { Array as expressionToArray } from '../expressionTo.js'; -import { describe, expect, test } from 'vitest'; - -describe('expressionTo', () => { - describe('MemberExpression', () => { - test('with only identifiers', () => { - expect(expressionToArray(parse.expression('foo.bar.baz'))).toEqual([ - 'foo', - 'bar', - 'baz', - ]); - }); - - test('with one computed literal', () => { - expect(expressionToArray(parse.expression('foo["bar"].baz'))).toEqual([ - 'foo', - '"bar"', - 'baz', - ]); - }); - - test('with one computed identifier', () => { - expect(expressionToArray(parse.expression('foo[bar].baz'))).toEqual([ - 'foo', - 'bar', - 'baz', - ]); - }); - - test('with one computed object', () => { - expect( - expressionToArray(parse.expression('foo[{ a: "true"}].baz')), - ).toEqual(['foo', '{a: "true"}', 'baz']); - }); - - test('with one computed object with spread', () => { - expect(expressionToArray(parse.expression('foo[{ ...a }].baz'))).toEqual([ - 'foo', - '{...a}', - 'baz', - ]); - }); - - test('with one computed object with method', () => { - expect(expressionToArray(parse.expression('foo[{ a(){} }].baz'))).toEqual( - ['foo', '{a: }', 'baz'], - ); - }); - - test('with TSAsExpression', () => { - expect( - expressionToArray(parseTypescript.expression('(baz as X).prop')), - ).toEqual(['baz', 'prop']); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/findFunctionReturn-test.ts b/packages/react-docgen/src/utils/__tests__/findFunctionReturn-test.ts deleted file mode 100644 index 252542eb85c..00000000000 --- a/packages/react-docgen/src/utils/__tests__/findFunctionReturn-test.ts +++ /dev/null @@ -1,267 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { StringLiteral } from '@babel/types'; -import { parse, makeMockImporter, noopImporter } from '../../../tests/utils'; -import type { Importer } from '../../importer'; -import findFunctionReturn from '../findFunctionReturn.js'; -import { describe, expect, test } from 'vitest'; - -const predicate = (path: NodePath): boolean => - path.isStringLiteral() && - (path.node.value === 'value' || path.node.value === 'wrong'); - -const value = '"value"'; - -function expectValue(received: NodePath | undefined) { - expect(received).not.toBeUndefined(); - expect(received?.node.type).toBe('StringLiteral'); - expect((received?.node as StringLiteral).value).toBe('value'); -} - -describe('findFunctionReturn', () => { - const wrongFunction = `const wrong = () => "wrong";`; - const functionStyle: Record< - string, - [(name: string, expr: string) => string, string] - > = { - ArrowExpression: [ - (name: string, expr: string): string => `var ${name} = () => (${expr});`, - 'declarations.0.init', - ], - ArrowBlock: [ - (name: string, expr: string): string => - `var ${name} = () => { ${wrongFunction}return (${expr}); };`, - 'declarations.0.init', - ], - FunctionExpression: [ - (name: string, expr: string): string => - `var ${name} = function () { ${wrongFunction}return (${expr}); }`, - 'declarations.0.init', - ], - FunctionDeclaration: [ - (name: string, expr: string): string => - `function ${name} () { ${wrongFunction}return (${expr}); }`, - '', - ], - }; - - const modifiers = { - default: (): string => value, - 'conditional consequent': (): string => `x ? ${value} : null`, - 'conditional alternate': (): string => `x ? null : ${value}`, - 'OR left': (): string => `${value} || null`, - 'AND right': (): string => `x && ${value}`, - }; - - type ComponentFactory = (name: string, expression: string) => string; - - const cases = { - 'no reference': [ - (expr: string, componentFactory: ComponentFactory): string => - `${componentFactory('Foo', expr)}`, - 'body.0', - ], - 'with Identifier reference': [ - (expr: string, componentFactory: ComponentFactory): string => ` - var variable = (${expr}); - ${componentFactory('Foo', 'variable')} - `, - 'body.1', - ], - }; - - Object.entries(functionStyle).forEach(([name, style]) => { - cases[`with ${name} reference`] = [ - (expr: string, componentFactory: ComponentFactory): string => ` - ${style[0]('subfunc', expr)} - ${componentFactory('Foo', 'subfunc()')} - `, - 'body.1', - ]; - }); - - const negativeModifiers = { - 'nested ArrowExpression': (expr: string): string => `() => ${expr}`, - 'nested ArrowBlock': (expr: string): string => `() => { return ${expr} }`, - 'nested FunctionExpression': (expr: string): string => - `function () { return ${expr} }`, - }; - - Object.keys(cases).forEach((name) => { - const [caseFactory, caseSelector] = cases[name]; - - describe(name, () => { - Object.entries(functionStyle).forEach( - ([functionName, [functionFactory, functionSelector]]) => { - describe(functionName, () => { - Object.keys(modifiers).forEach((modifierName) => { - const modifierFactory = modifiers[modifierName]; - - test(modifierName, () => { - const code = caseFactory(modifierFactory(), functionFactory); - const def: NodePath = parse(code).get( - `${caseSelector}.${functionSelector}`.replace(/\.$/, ''), - ) as NodePath; - - expectValue(findFunctionReturn(def, predicate)); - }); - }); - - Object.keys(negativeModifiers).forEach((modifierName) => { - const modifierFactory = negativeModifiers[modifierName]; - - test(modifierName, () => { - const code = caseFactory(modifierFactory(), functionFactory); - - const def: NodePath = parse(code).get( - `${caseSelector}.${functionSelector}`.replace(/\.$/, ''), - ) as NodePath; - - expect(findFunctionReturn(def, predicate)).toBeUndefined(); - }); - }); - }); - }, - ); - }); - }); - - describe('resolving return values', () => { - function testReturnValues( - desc: string, - src: string, - importer: Importer = noopImporter, - ) { - test(desc, () => { - const def = parse(src, importer).get('body')[0]; - - expectValue(findFunctionReturn(def, predicate)); - }); - } - - const mockImporter = makeMockImporter({ - bar: (stmtLast) => stmtLast(`export default "value";`).get('declaration'), - }); - - test('handles recursive function calls', () => { - const def = parse.statement(` - function Foo (props) { - return props && Foo(props); - } - `); - - expect(findFunctionReturn(def, predicate)).toBeUndefined(); - }); - - testReturnValues( - 'does not see ifs as separate block', - ` - function Foo (props) { - if (x) { - return "value"; - } - } - `, - ); - - testReturnValues( - 'handles simple resolves', - ` - function Foo (props) { - function bar() { - return "value"; - } - - return bar(); - } - `, - ); - - testReturnValues( - 'handles reference resolves', - ` - function Foo (props) { - var result = bar(); - - return result; - - function bar() { - return "value"; - } - } - `, - ); - - testReturnValues( - 'handles shallow member call expression resolves', - ` - function Foo (props) { - var shallow = { - shallowMember() { - return "value"; - } - }; - - return shallow.shallowMember(); - } - `, - ); - - testReturnValues( - 'handles deep member call expression resolves', - ` - function Foo (props) { - var obj = { - deep: { - member() { - return "value"; - } - } - }; - - return obj.deep.member(); - } - `, - ); - - testReturnValues( - 'handles external reference member call expression resolves', - ` - function Foo (props) { - var member = () => "value"; - var obj = { - deep: { - member: member - } - }; - - return obj.deep.member(); - } - `, - ); - - testReturnValues( - 'handles all sorts of JavaScript things', - ` - function Foo (props) { - var external = { - member: () => "value" - }; - var obj = {external}; - - return obj.external.member(); - } - `, - ); - - testReturnValues( - 'resolves imported values as return', - ` - function Foo (props) { - return bar; - } - import bar from 'bar'; - `, - mockImporter, - ); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/flowUtilityTypes-test.ts b/packages/react-docgen/src/utils/__tests__/flowUtilityTypes-test.ts deleted file mode 100644 index 19d6aa85118..00000000000 --- a/packages/react-docgen/src/utils/__tests__/flowUtilityTypes-test.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { - unwrapUtilityType, - isSupportedUtilityType, -} from '../flowUtilityTypes.js'; -import { parse } from '../../../tests/utils'; -import type { NodePath } from '@babel/traverse'; -import type { GenericTypeAnnotation, TypeAlias } from '@babel/types'; -import { describe, expect, test } from 'vitest'; - -describe('flowTypeUtilities', () => { - describe('unwrapUtilityType', () => { - test('correctly unwraps', () => { - const def = parse.statement(` - type A = $ReadOnly<{ foo: string }> - `); - - expect(unwrapUtilityType(def.get('right'))).toBe( - (def.get('right') as NodePath) - .get('typeParameters') - .get('params')[0], - ); - }); - - test('correctly unwraps double', () => { - const def = parse.statement(` - type A = $ReadOnly<$ReadOnly<{ foo: string }>> - `); - - expect(unwrapUtilityType(def.get('right'))).toBe( - ( - (def.get('right') as NodePath) - .get('typeParameters') - .get('params')[0] as NodePath - ) - .get('typeParameters') - .get('params')[0], - ); - }); - - test('correctly unwraps triple', () => { - const def = parse.statement(` - type A = $ReadOnly<$ReadOnly<$ReadOnly<{ foo: string }>>> - `); - - expect(unwrapUtilityType(def.get('right'))).toBe( - ( - ( - (def.get('right') as NodePath) - .get('typeParameters') - .get('params')[0] as NodePath - ) - .get('typeParameters') - .get('params')[0] as NodePath - ) - .get('typeParameters') - .get('params')[0], - ); - }); - }); - - describe('isSupportedUtilityType', () => { - test('correctly returns true for $Exact', () => { - const def = parse.statement(` - type A = $Exact<{ foo: string }> - `); - - expect(isSupportedUtilityType(def.get('right'))).toBe(true); - }); - - test('correctly returns true for $ReadOnly', () => { - const def = parse.statement(` - type A = $ReadOnly<{ foo: string }> - `); - - expect(isSupportedUtilityType(def.get('right'))).toBe(true); - }); - - test('correctly returns false for invalid type', () => { - const def = parse.statement(` - type A = $Homer<{ foo: string }> - `); - - expect(isSupportedUtilityType(def.get('right'))).toBe(false); - }); - - test('correctly returns false for QualifiedTypeIdentifier', () => { - const def = parse.statement(` - type A = $Homer.Marge<{ foo: string }> - `); - - expect(isSupportedUtilityType(def.get('right'))).toBe(false); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getClassMemberValuePath-test.ts b/packages/react-docgen/src/utils/__tests__/getClassMemberValuePath-test.ts deleted file mode 100644 index 4883bd91eab..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getClassMemberValuePath-test.ts +++ /dev/null @@ -1,123 +0,0 @@ -import getClassMemberValuePath from '../getClassMemberValuePath.js'; -import { parse } from '../../../tests/utils'; -import type { ClassDeclaration, ClassExpression } from '@babel/types'; -import { describe, expect, test } from 'vitest'; - -describe('getClassMemberValuePath', () => { - describe('ClassDeclaration', () => { - describe('MethodDefinitions', () => { - test('finds "normal" method definitions', () => { - const def = parse.statement(` - class Foo { - render() {} - } - `); - - expect(getClassMemberValuePath(def, 'render')).toMatchSnapshot(); - }); - - test('finds computed method definitions with literal keys', () => { - const def = parse.statement(` - class Foo { - ['render']() {} - } - `); - - expect(getClassMemberValuePath(def, 'render')).toMatchSnapshot(); - }); - - test('ignores computed method definitions with expression', () => { - const def = parse.statement(` - class Foo { - [render]() {} - } - `); - - expect(getClassMemberValuePath(def, 'render')).toBeNull(); - }); - }); - - describe('Getters and Setters', () => { - test('finds getters', () => { - const def = parse.statement(` - class Foo { - get foo() {} - } - `); - - expect(getClassMemberValuePath(def, 'foo')).toMatchSnapshot(); - }); - - test('ignores setters', () => { - const def = parse.statement(` - class Foo { - set foo(val) {} - } - `); - - expect(getClassMemberValuePath(def, 'foo')).toBeNull(); - }); - }); - - describe('ClassProperty', () => { - test('finds "normal" class properties', () => { - const def = parse.statement(` - class Foo { - foo = 42; - } - `); - - expect(getClassMemberValuePath(def, 'foo')).toEqual( - def.get('body').get('body')[0].get('value'), - ); - }); - }); - - describe('private', () => { - test('ignores private class properties', () => { - const def = parse.statement(` - class Foo { - #foo = 42; - } - `); - - expect(getClassMemberValuePath(def, 'foo')).toBeNull(); - }); - - test('ignores private class methods', () => { - const def = parse.statement(` - class Foo { - #foo() {} - } - `); - - expect(getClassMemberValuePath(def, 'foo')).toBeNull(); - }); - - test('finds "normal" class properties with private present', () => { - const def = parse.statement(` - class Foo { - #private = 54; - foo = 42; - } - `); - - expect(getClassMemberValuePath(def, 'foo')).toBe( - def.get('body').get('body')[1].get('value'), - ); - }); - }); - }); - - describe('ClassExpression', () => { - test('finds "normal" method definitions', () => { - const def = parse.expression(` - class Foo { - render() {} - } - `); - - expect(getClassMemberValuePath(def, 'render')).toMatchSnapshot(); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getFlowType-test.ts b/packages/react-docgen/src/utils/__tests__/getFlowType-test.ts deleted file mode 100644 index cd28f434011..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getFlowType-test.ts +++ /dev/null @@ -1,1725 +0,0 @@ -import getFlowType from '../getFlowType.js'; -import { parse, makeMockImporter } from '../../../tests/utils'; -import type { - ExportNamedDeclaration, - ExpressionStatement, - FlowType, - Identifier, - TypeAlias, - TypeCastExpression, - VariableDeclaration, -} from '@babel/types'; -import type { NodePath } from '@babel/traverse'; -import { describe, expect, test } from 'vitest'; - -describe('getFlowType', () => { - const mockImporter = makeMockImporter({ - abc: (stmt) => - stmt(` - export type abc = number; - `).get('declaration') as NodePath, - - def: (stmt) => - stmt(` - export type def = boolean; - `).get('declaration') as NodePath, - - xyz: (stmt) => - stmt(` - export type xyz = string; - `).get('declaration') as NodePath, - - maybe: (stmt) => - stmt(` - export type maybe = ?string; - `).get('declaration') as NodePath, - - barbaz: (stmt) => - stmt(` - export type barbaz = "bar" | "baz"; - `).get('declaration') as NodePath, - - recTup: (stmt) => - stmt(` - import type { abc } from 'abc'; - import type { xyz } from 'xyz'; - export type recTup = [abc, xyz]; - `).get('declaration') as NodePath, - - MyType: (stmt) => - stmt(` - export type MyType = { a: string, b: ?notImported }; - `).get('declaration') as NodePath, - - MyGenericType: (stmt) => - stmt(` - export type MyType = { a: T, b: Array }; - `).get('declaration') as NodePath, - - fruits: (stmt) => - stmt(` - export default { - 'apple': '🍎', - 'banana': '🍌', - }; - `).get('declaration'), - - otherFruits: (stmt) => - stmt(` - export type OtherFruits = { orange: string }; - `).get('declaration') as NodePath, - }); - - test('detects simple types', () => { - const simplePropTypes = [ - 'string', - 'number', - 'boolean', - 'any', - 'mixed', - 'null', - 'void', - 'empty', - 'Object', - 'Function', - 'Boolean', - 'String', - 'Number', - ]; - - simplePropTypes.forEach((type) => { - const typePath = parse - .expression('x: ' + type) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ name: type }); - }); - }); - - test('detects literal types', () => { - const literalTypes = ['"foo"', 1234, true]; - - literalTypes.forEach((value) => { - const typePath = parse - .expression(`x: ${value}`) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'literal', - value: `${value}`, - }); - }); - }); - - test('detects external type', () => { - const typePath = parse - .expression('x: xyz') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ name: 'xyz' }); - }); - - test('resolves an imported type', () => { - const typePath = ( - parse - .statement( - ` - (x: xyz); - import type { xyz } from 'xyz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'string', - }); - }); - - test('detects external nullable type', () => { - const typePath = parse - .expression('x: ?xyz') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'xyz', - nullable: true, - }); - }); - - test('resolves an imported nullable type', () => { - const typePath = ( - parse - .statement( - ` - (x: ?xyz); - import type { xyz } from 'xyz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'string', - nullable: true, - }); - }); - - test('detects array type shorthand optional', () => { - const typePath = parse - .expression('x: ?number[]') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'Array', - elements: [{ name: 'number' }], - raw: 'number[]', - nullable: true, - }); - }); - - test('detects array type shorthand optional type', () => { - const typePath = parse - .expression('x: (?number)[]') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'Array', - elements: [{ name: 'number', nullable: true }], - raw: '(?number)[]', - }); - }); - - test('detects array type shorthand', () => { - const typePath = parse - .expression('x: number[]') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'Array', - elements: [{ name: 'number' }], - raw: 'number[]', - }); - }); - - test('detects array type', () => { - const typePath = parse - .expression('x: Array') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'Array', - elements: [{ name: 'number' }], - raw: 'Array', - }); - }); - - test('resolves imported types used for arrays', () => { - let typePath = ( - parse - .statement( - ` - (x: Array); - import type { xyz } from 'xyz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'Array', - elements: [{ name: 'string' }], - raw: 'Array', - }); - - typePath = ( - parse - .statement( - ` - (x: xyz[]); - import type { xyz } from 'xyz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - expect(getFlowType(typePath)).toEqual({ - name: 'Array', - elements: [{ name: 'string' }], - raw: 'xyz[]', - }); - - typePath = ( - parse - .statement( - ` - (x: ?xyz[]); - import type { xyz } from 'xyz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - expect(getFlowType(typePath)).toEqual({ - name: 'Array', - elements: [{ name: 'string' }], - raw: 'xyz[]', - nullable: true, - }); - - typePath = ( - parse - .statement( - ` - (x: (?xyz)[]); - import type { xyz } from 'xyz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - expect(getFlowType(typePath)).toEqual({ - name: 'Array', - elements: [{ name: 'string', nullable: true }], - raw: '(?xyz)[]', - }); - }); - - test('detects array type with multiple types', () => { - const typePath = parse - .expression('x: Array') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'Array', - elements: [{ name: 'number' }, { name: 'xyz' }], - raw: 'Array', - }); - }); - - test('resolves array type with multiple imported types', () => { - const typePath = ( - parse - .statement( - ` - (x: Array); - import type { abc } from 'abc'; - import type { xyz } from 'xyz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'Array', - elements: [{ name: 'number' }, { name: 'string' }], - raw: 'Array', - }); - }); - - test('detects class type', () => { - const typePath = parse - .expression('x: Class') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'Class', - elements: [{ name: 'Boolean' }], - raw: 'Class', - }); - }); - - test('resolves imported subtype for class type', () => { - const typePath = ( - parse - .statement( - ` - (x: Class); - import type { xyz } from 'xyz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'Class', - elements: [{ name: 'string' }], - raw: 'Class', - }); - }); - - test('detects function type with subtype', () => { - const typePath = parse - .expression('x: Function') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'Function', - elements: [{ name: 'xyz' }], - raw: 'Function', - }); - }); - - test('resolves imported subtype for function type', () => { - const typePath = ( - parse - .statement( - ` - (x: Function); - import type { xyz } from 'xyz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'Function', - elements: [{ name: 'string' }], - raw: 'Function', - }); - }); - - test('detects object types', () => { - const typePath = parse - .expression('x: { a: string, b?: xyz }') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'object', - signature: { - properties: [ - { key: 'a', value: { name: 'string', required: true } }, - { key: 'b', value: { name: 'xyz', required: false } }, - ], - }, - raw: '{ a: string, b?: xyz }', - }); - }); - - test('detects object types with descriptions', () => { - const typePath = parse - .expression( - `x: { - /** A */ - a: string, - /** B */ - b?: xyz - }`, - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toMatchSnapshot(); - }); - - test('detects object types with maybe type', () => { - const typePath = parse - .expression('x: { a: string, b: ?xyz }') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toMatchSnapshot(); - }); - - test('resolves imported types used for objects', () => { - const typePath = ( - parse - .statement( - ` - (x: { a: abc, b: ?xyz, c?: xyz, d: maybe, e?: maybe }); - import type { abc } from 'abc'; - import type { xyz } from 'xyz'; - import type { maybe } from 'maybe'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'object', - signature: { - properties: [ - { key: 'a', value: { name: 'number', required: true } }, - { - key: 'b', - value: { name: 'string', nullable: true, required: false }, - }, - { - key: 'c', - value: { name: 'string', nullable: true, required: false }, - }, - { - key: 'd', - value: { name: 'string', nullable: true, required: false }, - }, - { - key: 'e', - value: { name: 'string', nullable: true, required: false }, - }, - ], - }, - raw: '{ a: abc, b: ?xyz, c?: xyz, d: maybe, e?: maybe }', - }); - }); - - test('detects union type', () => { - const typePath = parse - .expression('x: string | xyz | "foo" | void') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'union', - elements: [ - { name: 'string' }, - { name: 'xyz' }, - { name: 'literal', value: '"foo"' }, - { name: 'void' }, - ], - raw: 'string | xyz | "foo" | void', - }); - }); - - test('resolves imported types within union type', () => { - const typePath = ( - parse - .statement( - ` - (x: string | barbaz | "foo" | void); - import type { barbaz } from 'barbaz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'union', - elements: [ - { name: 'string' }, - { - name: 'union', - elements: [ - { name: 'literal', value: '"bar"' }, - { name: 'literal', value: '"baz"' }, - ], - raw: '"bar" | "baz"', - }, - { name: 'literal', value: '"foo"' }, - { name: 'void' }, - ], - raw: 'string | barbaz | "foo" | void', - }); - }); - - test('detects intersection type', () => { - const typePath = parse - .expression('x: string & xyz & "foo" & void') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'intersection', - elements: [ - { name: 'string' }, - { name: 'xyz' }, - { name: 'literal', value: '"foo"' }, - { name: 'void' }, - ], - raw: 'string & xyz & "foo" & void', - }); - }); - - test('resolves imported types within intersection type', () => { - const typePath = ( - parse - .statement( - ` - (x: string & barbaz & "foo" & void); - import type { barbaz } from 'barbaz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'intersection', - elements: [ - { name: 'string' }, - { - name: 'union', - elements: [ - { name: 'literal', value: '"bar"' }, - { name: 'literal', value: '"baz"' }, - ], - raw: '"bar" | "baz"', - }, - { name: 'literal', value: '"foo"' }, - { name: 'void' }, - ], - raw: 'string & barbaz & "foo" & void', - }); - }); - - test('detects function signature type', () => { - const typePath = parse - .expression( - 'x: (p1: number, p2: ?string, ...rest: Array) => boolean', - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'function', - signature: { - arguments: [ - { name: 'p1', type: { name: 'number' } }, - { name: 'p2', type: { name: 'string', nullable: true } }, - { - name: 'rest', - rest: true, - type: { - name: 'Array', - elements: [{ name: 'string' }], - raw: 'Array', - }, - }, - ], - return: { name: 'boolean' }, - }, - raw: '(p1: number, p2: ?string, ...rest: Array) => boolean', - }); - }); - - test('detects function signature types without parameter names', () => { - const typePath = parse - .expression('x: (number, ?string) => boolean') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'function', - signature: { - arguments: [ - { name: '', type: { name: 'number' } }, - { name: '', type: { name: 'string', nullable: true } }, - ], - return: { name: 'boolean' }, - }, - raw: '(number, ?string) => boolean', - }); - }); - - test('detects function signature type with single parmeter without name', () => { - const typePath = parse - .expression('x: string => boolean') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'function', - signature: { - arguments: [{ name: '', type: { name: 'string' } }], - return: { name: 'boolean' }, - }, - raw: 'string => boolean', - }); - }); - - test('detects callable signature type', () => { - const typePath = parse - .expression( - 'x: { (str: string): string, token: string }', - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'object', - signature: { - constructor: { - name: 'signature', - type: 'function', - signature: { - arguments: [{ name: 'str', type: { name: 'string' } }], - return: { name: 'string' }, - }, - raw: '(str: string): string', - }, - properties: [ - { key: 'token', value: { name: 'string', required: true } }, - ], - }, - raw: '{ (str: string): string, token: string }', - }); - }); - - test('resolves function signature types with imported types', () => { - let typePath = ( - parse - .statement( - ` - (x: (p1: abc, p2: ?xyz, ...rest: Array) => def); - import type { abc } from 'abc'; - import type { def } from 'def'; - import type { xyz } from 'xyz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'function', - signature: { - arguments: [ - { name: 'p1', type: { name: 'number' } }, - { name: 'p2', type: { name: 'string', nullable: true } }, - { - name: 'rest', - rest: true, - type: { - name: 'Array', - elements: [{ name: 'string', nullable: true }], - raw: 'Array', - }, - }, - ], - return: { name: 'boolean' }, - }, - raw: '(p1: abc, p2: ?xyz, ...rest: Array) => def', - }); - - typePath = ( - parse - .statement( - ` - (x: (abc, ?xyz) => def); - import type { abc } from 'abc'; - import type { def } from 'def'; - import type { xyz } from 'xyz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'function', - signature: { - arguments: [ - { name: '', type: { name: 'number' } }, - { name: '', type: { name: 'string', nullable: true } }, - ], - return: { name: 'boolean' }, - }, - raw: '(abc, ?xyz) => def', - }); - - typePath = ( - parse - .statement( - ` - (x: xyz => def); - import type { def } from 'def'; - import type { xyz } from 'xyz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'function', - signature: { - arguments: [{ name: '', type: { name: 'string' } }], - return: { name: 'boolean' }, - }, - raw: 'xyz => def', - }); - - typePath = ( - parse - .statement( - ` - (x: { (str: xyz): abc, token: def }); - import type { abc } from 'abc'; - import type { def } from 'def'; - import type { xyz } from 'xyz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'object', - signature: { - constructor: { - name: 'signature', - type: 'function', - signature: { - arguments: [{ name: 'str', type: { name: 'string' } }], - return: { name: 'number' }, - }, - raw: '(str: xyz): abc', - }, - properties: [ - { key: 'token', value: { name: 'boolean', required: true } }, - ], - }, - raw: '{ (str: xyz): abc, token: def }', - }); - }); - - test('detects map signature', () => { - const typePath = parse - .expression( - 'x: { [key: string]: number, [key: "xl"]: string, token: "a" | "b" }', - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'object', - signature: { - properties: [ - { - key: { name: 'string' }, - value: { name: 'number', required: true }, - }, - { - key: { name: 'literal', value: '"xl"' }, - value: { name: 'string', required: true }, - }, - { - key: 'token', - value: { - name: 'union', - required: true, - raw: '"a" | "b"', - elements: [ - { name: 'literal', value: '"a"' }, - { name: 'literal', value: '"b"' }, - ], - }, - }, - ], - }, - raw: '{ [key: string]: number, [key: "xl"]: string, token: "a" | "b" }', - }); - }); - - test('resolves imported types in map signature', () => { - const typePath = ( - parse - .statement( - ` - (x: { [key: xyz]: abc, [key: "xl"]: def, token: barbaz }); - import type { abc } from 'abc'; - import type { def } from 'def'; - import type { xyz } from 'xyz'; - import type { barbaz } from 'barbaz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'object', - signature: { - properties: [ - { - key: { name: 'string' }, - value: { name: 'number', required: true }, - }, - { - key: { name: 'literal', value: '"xl"' }, - value: { name: 'boolean', required: true }, - }, - { - key: 'token', - value: { - name: 'union', - required: true, - raw: '"bar" | "baz"', - elements: [ - { name: 'literal', value: '"bar"' }, - { name: 'literal', value: '"baz"' }, - ], - }, - }, - ], - }, - raw: '{ [key: xyz]: abc, [key: "xl"]: def, token: barbaz }', - }); - }); - - test('detects tuple signature', () => { - const typePath = parse - .expression('x: [string, number]') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'tuple', - elements: [{ name: 'string' }, { name: 'number' }], - raw: '[string, number]', - }); - }); - - test('detects tuple in union signature', () => { - const typePath = parse - .expression('x: [string, number] | [number, string]') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'union', - elements: [ - { - name: 'tuple', - elements: [{ name: 'string' }, { name: 'number' }], - raw: '[string, number]', - }, - { - name: 'tuple', - elements: [{ name: 'number' }, { name: 'string' }], - raw: '[number, string]', - }, - ], - raw: '[string, number] | [number, string]', - }); - }); - - test('resolves imported types used in tuple signature', () => { - let typePath = ( - parse - .statement( - ` - (x: [xyz, abc]); - import type { abc } from 'abc'; - import type { xyz } from 'xyz'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'tuple', - elements: [{ name: 'string' }, { name: 'number' }], - raw: '[xyz, abc]', - }); - - typePath = ( - parse - .statement( - ` - (x: [xyz, abc] | recTup); - import type { abc } from 'abc'; - import type { xyz } from 'xyz'; - import type { recTup } from 'recTup'; - `, - mockImporter, - ) - .get('expression') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getFlowType(typePath)).toEqual({ - name: 'union', - elements: [ - { - name: 'tuple', - elements: [{ name: 'string' }, { name: 'number' }], - raw: '[xyz, abc]', - }, - { - name: 'tuple', - elements: [{ name: 'number' }, { name: 'string' }], - raw: '[abc, xyz]', - }, - ], - raw: '[xyz, abc] | recTup', - }); - }); - - test('resolves types in scope', () => { - const typePath = ( - parse - .statement( - ` - var x: MyType = 2; - - type MyType = string; - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'string', - }); - }); - - test('handles typeof types', () => { - const typePath = ( - parse - .statement( - ` - var x: typeof MyType = {}; - - type MyType = { a: string, b: ?xyz }; - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'object', - signature: { - properties: [ - { key: 'a', value: { name: 'string', required: true } }, - { key: 'b', value: { name: 'xyz', nullable: true, required: true } }, - ], - }, - raw: '{ a: string, b: ?xyz }', - }); - }); - - test('resolves typeof of imported types', () => { - const typePath = ( - parse - .statement( - ` - var x: typeof MyType = {}; - import type { MyType } from 'MyType'; - `, - mockImporter, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'object', - signature: { - properties: [ - { key: 'a', value: { name: 'string', required: true } }, - { - key: 'b', - value: { name: 'notImported', nullable: true, required: true }, - }, - ], - }, - raw: '{ a: string, b: ?notImported }', - }); - }); - - test('handles qualified type identifiers', () => { - const typePath = ( - parse - .statement( - ` - var x: MyType.x = {}; - - type MyType = { a: string, b: ?xyz }; - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'MyType.x', - }); - }); - - test('handles qualified type identifiers with params', () => { - const typePath = ( - parse - .statement( - ` - var x: MyType.x = {}; - - type MyType = { a: string, b: ?xyz }; - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'MyType.x', - raw: 'MyType.x', - elements: [ - { - name: 'any', - }, - ], - }); - }); - - test('handles generic types', () => { - const typePath = ( - parse - .statement( - ` - var x: MyType = {}; - - type MyType = { a: T, b: Array }; - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'object', - raw: '{ a: T, b: Array }', - signature: { - properties: [ - { - key: 'a', - value: { - name: 'string', - required: true, - }, - }, - { - key: 'b', - value: { - name: 'Array', - raw: 'Array', - required: true, - elements: [{ name: 'string' }], - }, - }, - ], - }, - }); - }); - - test('resolves imported types that need subtypes', () => { - const typePath = ( - parse - .statement( - ` - var x: MyGenericType = {}; - import type { MyGenericType } from 'MyGenericType'; - `, - mockImporter, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'object', - raw: '{ a: T, b: Array }', - signature: { - properties: [ - { - key: 'a', - value: { - name: 'string', - required: true, - }, - }, - { - key: 'b', - value: { - name: 'Array', - raw: 'Array', - required: true, - elements: [{ name: 'string' }], - }, - }, - ], - }, - }); - }); - - describe('React types', () => { - function testReactType(type, expected) { - const typePath = ( - parse - .statement( - ` - var x: ${type} = 2; - - type Props = { x: string }; - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - ...expected, - name: type.replace('.', '').replace(/<.+>/, ''), - raw: type, - }); - } - - const types = { - 'React.Node': {}, - 'React.Key': {}, - 'React.ElementType': {}, - 'React.ChildrenArray': { elements: [{ name: 'string' }] }, - 'React.Element': { elements: [{ name: 'any' }] }, - 'React.Ref': { elements: [{ name: 'Component' }] }, - 'React.ElementProps': { elements: [{ name: 'Component' }] }, - 'React.ElementRef': { elements: [{ name: 'Component' }] }, - 'React.ComponentType': { - elements: [ - { - name: 'signature', - raw: '{ x: string }', - signature: { - properties: [ - { key: 'x', value: { name: 'string', required: true } }, - ], - }, - type: 'object', - }, - ], - }, - 'React.StatelessFunctionalComponent': { - elements: [{ name: 'Props2' }], - }, - }; - - Object.keys(types).forEach((type) => { - test(type, () => testReactType(type, types[type])); - }); - }); - - test('resolves $Keys to union', () => { - const typePath = ( - parse - .statement( - ` - var x: $Keys = 2; - const CONTENTS = { - 'apple': '🍎', - 'banana': '🍌', - }; - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'union', - elements: [ - { name: 'literal', value: "'apple'" }, - { name: 'literal', value: "'banana'" }, - ], - raw: '$Keys', - }); - }); - - test('resolves $Keys without typeof to union', () => { - const typePath = ( - parse - .statement( - ` - var x: $Keys = 2; - const CONTENTS = { - 'apple': '🍎', - 'banana': '🍌', - }; - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'union', - elements: [ - { name: 'literal', value: "'apple'" }, - { name: 'literal', value: "'banana'" }, - ], - raw: '$Keys', - }); - }); - - test('resolves $Keys with an ObjectTypeAnnotation typeParameter to union', () => { - const typePath = ( - parse - .statement( - ` - var x: $Keys<{| apple: string, banana: string |}> = 2; - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'union', - elements: [ - { name: 'literal', value: 'apple' }, - { name: 'literal', value: 'banana' }, - ], - raw: '$Keys<{| apple: string, banana: string |}>', - }); - }); - - test('resolves $Keys with an ObjectTypeAnnotation typeParameter to union with an ObjectTypeSpreadProperty', () => { - const typePath = ( - parse - .statement( - ` - var x: $Keys<{| apple: string, banana: string, ...OtherFruits |}> = 2; - type OtherFruits = { orange: string } - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'union', - elements: [ - { name: 'literal', value: 'apple' }, - { name: 'literal', value: 'banana' }, - { name: 'literal', value: 'orange' }, - ], - raw: '$Keys<{| apple: string, banana: string, ...OtherFruits |}>', - }); - }); - - test('resolves $Keys to imported types', () => { - let typePath = ( - parse - .statement( - ` - var x: $Keys = 2; - import CONTENTS from 'fruits'; - `, - mockImporter, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'union', - elements: [ - { name: 'literal', value: "'apple'" }, - { name: 'literal', value: "'banana'" }, - ], - raw: '$Keys', - }); - - typePath = ( - parse - .statement( - ` - var x: $Keys = 2; - import CONTENTS from 'fruits'; - `, - mockImporter, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'union', - elements: [ - { name: 'literal', value: "'apple'" }, - { name: 'literal', value: "'banana'" }, - ], - raw: '$Keys', - }); - - typePath = ( - parse - .statement( - ` - var x: $Keys<{| apple: string, banana: string, ...OtherFruits |}> = 2; - import type { OtherFruits } from 'otherFruits'; - `, - mockImporter, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'union', - elements: [ - { name: 'literal', value: 'apple' }, - { name: 'literal', value: 'banana' }, - { name: 'literal', value: 'orange' }, - ], - raw: '$Keys<{| apple: string, banana: string, ...OtherFruits |}>', - }); - }); - - test('handles multiple references to one type', () => { - const typePath = ( - parse - .statement( - ` - let action: { a: Action, b: Action }; - type Action = {}; - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'object', - signature: { - properties: [ - { - key: 'a', - value: { - name: 'signature', - type: 'object', - required: true, - raw: '{}', - signature: { properties: [] }, - }, - }, - { - key: 'b', - value: { - name: 'signature', - type: 'object', - required: true, - raw: '{}', - signature: { properties: [] }, - }, - }, - ], - }, - raw: '{ a: Action, b: Action }', - }); - }); - - test('handles self-referencing type cycles', () => { - const typePath = ( - parse - .statement( - ` - let action: Action; - type Action = { subAction: Action }; - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'object', - signature: { - properties: [ - { key: 'subAction', value: { name: 'Action', required: true } }, - ], - }, - raw: '{ subAction: Action }', - }); - }); - - test('handles long type cycles', () => { - const typePath = ( - parse - .statement( - ` - let action: Action; - type Action = { subAction: SubAction }; - type SubAction = { subAction: SubSubAction }; - type SubSubAction = { subAction: SubSubSubAction }; - type SubSubSubAction = { rootAction: Action }; - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toEqual({ - name: 'signature', - type: 'object', - signature: { - properties: [ - { - key: 'subAction', - value: { - name: 'signature', - type: 'object', - required: true, - signature: { - properties: [ - { - key: 'subAction', - value: { - name: 'signature', - type: 'object', - required: true, - signature: { - properties: [ - { - key: 'subAction', - value: { - name: 'signature', - type: 'object', - required: true, - signature: { - properties: [ - { - key: 'rootAction', - value: { name: 'Action', required: true }, - }, - ], - }, - raw: '{ rootAction: Action }', - }, - }, - ], - }, - raw: '{ subAction: SubSubSubAction }', - }, - }, - ], - }, - raw: '{ subAction: SubSubAction }', - }, - }, - ], - }, - raw: '{ subAction: SubAction }', - }); - }); - - test('handles ObjectTypeSpreadProperty', () => { - const typePath = ( - parse - .statement( - ` - var x: {| apple: string, banana: string, ...OtherFruits |} = 2; - type OtherFruits = { orange: string } - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toMatchSnapshot(); - }); - - test('handles ObjectTypeSpreadProperty from imported types', () => { - const typePath = ( - parse - .statement( - ` - var x: {| apple: string, banana: string, ...MyType |} = 2; - import type { MyType } from 'MyType'; - `, - mockImporter, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toMatchSnapshot(); - }); - - test('handles unresolved ObjectTypeSpreadProperty', () => { - const typePath = ( - parse - .statement( - `var x: {| apple: string, banana: string, ...MyType |} = 2;`, - mockImporter, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toMatchSnapshot(); - }); - - test('handles nested ObjectTypeSpreadProperty', () => { - const typePath = ( - parse - .statement( - ` - var x: {| apple: string, banana: string, ...BreakfastFruits |} = 2; - type BreakfastFruits = { mango: string, ...CitrusFruits }; - type CitrusFruits = { orange: string, lemon: string }; - `, - mockImporter, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toMatchSnapshot(); - }); - - test('handles indexed access on interface', () => { - const typePath = ( - parse - .statement( - ` - var x: A["x"] = 2; - interface A { x: string }; - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toMatchSnapshot(); - }); - - test('handles indexed access on alias', () => { - const typePath = ( - parse - .statement( - ` - var x: A["x"] = 2; - type A = { x: string }; - `, - ) - .get('declarations')[0] - .get('id') as NodePath - ) - .get('typeAnnotation') - .get('typeAnnotation') as NodePath; - - expect(getFlowType(typePath)).toMatchSnapshot(); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getMemberExpressionRoot-test.ts b/packages/react-docgen/src/utils/__tests__/getMemberExpressionRoot-test.ts deleted file mode 100644 index 07dd2ebf932..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getMemberExpressionRoot-test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { MemberExpression } from '@babel/types'; -import { parse } from '../../../tests/utils'; -import getMemberExpressionRoot from '../getMemberExpressionRoot.js'; -import { describe, expect, test } from 'vitest'; - -describe('getMemberExpressionRoot', () => { - test('returns the root of a member expression', () => { - const root = getMemberExpressionRoot(parse.expression('foo.bar.baz')); - - expect(root).toMatchSnapshot(); - }); - - test('returns the same path if identifier', () => { - const id = parse.expression('foo'); - const root = getMemberExpressionRoot(id); - - expect(root).toMatchSnapshot(); - }); - - test('returns the same path if literal', () => { - const literal = parse.expression('1'); - const root = getMemberExpressionRoot(literal); - - expect(root).toMatchSnapshot(); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getMemberExpressionValuePath-test.ts b/packages/react-docgen/src/utils/__tests__/getMemberExpressionValuePath-test.ts deleted file mode 100644 index 2f4824ad175..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getMemberExpressionValuePath-test.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { parse } from '../../../tests/utils'; -import getMemberExpressionValuePath from '../getMemberExpressionValuePath.js'; -import { describe, expect, test } from 'vitest'; - -describe('getMemberExpressionValuePath', () => { - describe('MethodExpression', () => { - test('finds "normal" property definitions', () => { - const def = parse.statement(` - var Foo = () => {}; - Foo.propTypes = {}; - `); - - expect(getMemberExpressionValuePath(def, 'propTypes')).toBe( - def.parentPath.get('body')[1].get('expression').get('right'), - ); - }); - - test('ignores unrelated private field', () => { - const def = parse.statement( - ` - class Foo { - #isprivate = {}; - - classMethod() { - this.#isprivate = {}; - } - } - const Boo = () => {}; - Boo.propTypes = {}; - `, - 1, - ); - - expect(getMemberExpressionValuePath(def, 'propTypes')).toBe( - def.parentPath.get('body')[2].get('expression').get('right'), - ); - }); - - test('takes the correct property definitions', () => { - const def = parse.statement(` - var Foo = () => {}; - Foo.propTypes = {}; - Bar.propTypes = { unrelated: true }; - `); - - expect(getMemberExpressionValuePath(def, 'propTypes')).toBe( - def.parentPath.get('body')[1].get('expression').get('right'), - ); - }); - - test('finds computed property definitions with literal keys', () => { - const def = parse.statement(` - function Foo () {} - Foo['render'] = () => {}; - `); - - expect(getMemberExpressionValuePath(def, 'render')).toBe( - def.parentPath.get('body')[1].get('expression').get('right'), - ); - }); - - test('handles template literals', () => { - const def = parse.statement(` - var Foo = function Bar() {}; - Foo[\`some\${template}\`] = () => {}; - `); - - expect(getMemberExpressionValuePath(def, 'something')).toBeNull(); - }); - - test('ignores computed property definitions with expression', () => { - const def = parse.statement(` - var Foo = function Bar() {}; - Foo[imComputed] = () => {}; - `); - - expect(getMemberExpressionValuePath(def, 'imComputed')).toBeNull(); - }); - }); - describe('TaggedTemplateLiteral', () => { - test('finds "normal" property definitions', () => { - const def = parse.statement(` - var Foo = foo\`bar\` - Foo.propTypes = {}; - `); - - expect(getMemberExpressionValuePath(def, 'propTypes')).toBe( - def.parentPath.get('body')[1].get('expression').get('right'), - ); - }); - }); - describe('CallExpression', () => { - test('finds "normal" property definitions', () => { - const def = parse.statement(` - const Foo = system({is: "button"}, "space"); - Foo.propTypes = {}; - `); - - expect(getMemberExpressionValuePath(def, 'propTypes')).toBe( - def.parentPath.get('body')[1].get('expression').get('right'), - ); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getMemberValuePath-test.ts b/packages/react-docgen/src/utils/__tests__/getMemberValuePath-test.ts deleted file mode 100644 index 6d8da488ab8..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getMemberValuePath-test.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { parse } from '../../../tests/utils'; -import getPropertyValuePath from '../getPropertyValuePath.js'; -import getClassMemberValuePath from '../getClassMemberValuePath.js'; -import getMemberValuePath from '../getMemberValuePath.js'; -import getMemberExpressionValuePath from '../getMemberExpressionValuePath.js'; -import type { - CallExpression, - ClassDeclaration, - ClassExpression, - ObjectExpression, - TaggedTemplateExpression, -} from '@babel/types'; -import { describe, expect, test, vi } from 'vitest'; - -vi.mock('../getPropertyValuePath.js'); -vi.mock('../getClassMemberValuePath.js'); -vi.mock('../getMemberExpressionValuePath.js'); - -describe('getMemberValuePath', () => { - test('handles ObjectExpressions', () => { - const path = parse.expression('{}'); - - getMemberValuePath(path, 'foo'); - expect(getPropertyValuePath).toBeCalledWith(path, 'foo'); - }); - - test('handles ClassDeclarations', () => { - const path = parse.statement('class Foo {}'); - - getMemberValuePath(path, 'foo'); - expect(getClassMemberValuePath).toBeCalledWith(path, 'foo'); - }); - - test('handles TaggedTemplateLiterals', () => { - const path = parse.expression('foo``'); - - getMemberValuePath(path, 'foo'); - expect(getMemberExpressionValuePath).toBeCalledWith(path, 'foo'); - }); - - test('handles ClassExpressions', () => { - const path = parse.expression('class {}'); - - getMemberValuePath(path, 'foo'); - expect(getClassMemberValuePath).toBeCalledWith(path, 'foo'); - }); - - test('handles CallExpressions', () => { - const path = parse.expression( - 'system({is: "button"}, "space")', - ); - - getMemberValuePath(path, 'foo'); - expect(getMemberExpressionValuePath).toBeCalledWith(path, 'foo'); - }); - - describe('tries defaultProps synonyms', () => { - test('with object', () => { - const path = parse.expression('{}'); - - getMemberValuePath(path, 'defaultProps'); - expect(getPropertyValuePath).toBeCalledWith(path, 'defaultProps'); - expect(getPropertyValuePath).toBeCalledWith(path, 'getDefaultProps'); - }); - - test('with class', () => { - const path = parse.statement('class Foo {}'); - - getMemberValuePath(path, 'defaultProps'); - expect(getClassMemberValuePath).toBeCalledWith(path, 'defaultProps'); - expect(getClassMemberValuePath).toBeCalledWith(path, 'getDefaultProps'); - }); - }); - - test('returns the result of getPropertyValuePath and getClassMemberValuePath', () => { - const mockPath = parse.expression('42'); - const mockPath2 = parse.expression('21'); - - vi.mocked(getPropertyValuePath).mockReturnValue(mockPath); - vi.mocked(getClassMemberValuePath).mockReturnValue(mockPath2); - let path = parse.expression('{}'); - - expect(getMemberValuePath(path, 'defaultProps')).toBe(mockPath); - - path = parse.statement('class Foo {}'); - - expect(getMemberValuePath(path, 'defaultProps')).toBe(mockPath2); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getMembers-test.ts b/packages/react-docgen/src/utils/__tests__/getMembers-test.ts deleted file mode 100644 index b0929dadfb4..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getMembers-test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { parse } from '../../../tests/utils'; -import getMembers from '../getMembers.js'; -import { describe, expect, test } from 'vitest'; - -describe('getMembers', () => { - test('finds all "members" "inside" a MemberExpression', () => { - const members = getMembers(parse.expression('foo.bar(123)(456)[baz][42]')); - - expect(members).toMatchSnapshot(); - }); - - test('includes the root if option set to true', () => { - const members = getMembers(parse.expression('foo.bar(123)[baz]'), true); - - expect(members).toMatchSnapshot(); - }); - - test('does work with custom expressions in chain', () => { - const members = getMembers(parse.expression('foo.bar(123)["" + ""]')); - - expect(members).toMatchSnapshot(); - }); - - test('does work with custom expressions in arguments', () => { - const members = getMembers(parse.expression('foo.bar(123 + 123)["baz"]')); - - expect(members).toMatchSnapshot(); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getMethodDocumentation-test.ts b/packages/react-docgen/src/utils/__tests__/getMethodDocumentation-test.ts deleted file mode 100644 index ee016c7ff35..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getMethodDocumentation-test.ts +++ /dev/null @@ -1,425 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { - AssignmentExpression, - ClassDeclaration, - ClassMethod, - ClassPrivateMethod, - ClassProperty, - ExpressionStatement, - ObjectExpression, - ObjectMethod, -} from '@babel/types'; -import { parse, makeMockImporter, parseTypescript } from '../../../tests/utils'; -import getMethodDocumentation from '../getMethodDocumentation.js'; -import { describe, expect, test } from 'vitest'; - -describe('getMethodDocumentation', () => { - const mockImporter = makeMockImporter({ - hello: (stmt) => - stmt(` - export default () => {}; - `).get('declaration'), - - bar: (stmt) => - stmt(` - export default (bar: number) => {}; - `).get('declaration'), - - baz: (stmt) => - stmt(` - export default (): number => {}; - `).get('declaration'), - }); - - describe('name', () => { - test('extracts the method name', () => { - const def = parse.statement(` - class Foo { - hello() {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toEqual({ - name: 'hello', - docblock: null, - modifiers: [], - returns: null, - params: [], - }); - }); - - test('handles function assignment', () => { - const def = parse.statement(` - class Foo { - hello = () => {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toEqual({ - name: 'hello', - docblock: null, - modifiers: [], - returns: null, - params: [], - }); - }); - - test('handles computed method name', () => { - const def = parse.statement(` - class Foo { - [foo]() {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toMatchSnapshot(); - }); - - test('ignores complex computed method name', () => { - const def = parse.statement(` - class Foo { - [() => {}]() {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toMatchSnapshot(); - }); - - test('resolves assignment of imported function', () => { - const def = parse.statement( - ` - class Foo { - hello = hello; - } - import hello from 'hello'; - `, - mockImporter, - ); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toEqual({ - name: 'hello', - docblock: null, - modifiers: [], - returns: null, - params: [], - }); - }); - }); - - describe('docblock', () => { - test('extracts the method docblock', () => { - const def = parse.statement(` - class Foo { - /** - * Don't use this! - */ - foo() {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toEqual({ - name: 'foo', - docblock: "Don't use this!", - modifiers: [], - returns: null, - params: [], - }); - }); - - test('extracts docblock on property assignment', () => { - const def = parse.statement(` - class Foo { - /** - * Don't use this! - */ - foo = () => {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toEqual({ - name: 'foo', - docblock: "Don't use this!", - modifiers: [], - returns: null, - params: [], - }); - }); - - test('extracts docblock on function assignment', () => { - const method = parse - .statementLast( - `const Foo = () => {} - /** - * Don't use this! - */ - Foo.foo = () => {} - `, - ) - .get('expression') as NodePath; - - expect(getMethodDocumentation(method)).toEqual({ - name: 'foo', - docblock: "Don't use this!", - modifiers: ['static'], - returns: null, - params: [], - }); - }); - }); - - describe('parameters', () => { - test('extracts flow type info', () => { - const def = parse.statement(` - class Foo { - foo(bar: number) {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toMatchSnapshot(); - }); - - test('extracts flow type info', () => { - const def = parseTypescript.statement(` - class Foo { - foo(bar: number) {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toMatchSnapshot(); - }); - - test('does not add type parameters to alias', () => { - const def = parseTypescript.statement(` - class Foo { - foo(bar: Foo) {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toMatchSnapshot(); - }); - - test('extracts flow type info on function assignment', () => { - const def = parse.statement(` - class Foo { - foo = (bar: number) => {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toMatchSnapshot(); - }); - - test('resolves flow type info on imported functions', () => { - const def = parse.statement( - ` - class Foo { - foo = bar - } - import bar from 'bar'; - `, - mockImporter, - ); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toMatchSnapshot(); - }); - - describe('modifiers', () => { - function methodModifiersDoc(modifiers) { - return { - name: 'foo', - docblock: null, - modifiers, - returns: null, - params: [], - }; - } - - test('detects no modifiers', () => { - const def = parse.statement(` - class Foo { - foo() {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toEqual(methodModifiersDoc([])); - }); - - test('detects static functions', () => { - const def = parse.statement(` - class Foo { - static foo() {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toEqual( - methodModifiersDoc(['static']), - ); - }); - - test('detects manually set static functions', () => { - const def = parse.expression(`{ foo() {} }`); - const method = def.get('properties')[0] as NodePath; - - expect(getMethodDocumentation(method, { isStatic: true })).toEqual( - methodModifiersDoc(['static']), - ); - }); - - test('detects generators', () => { - const def = parse.statement(` - class Foo { - *foo () {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toEqual( - methodModifiersDoc(['generator']), - ); - }); - - test('detects async functions', () => { - const def = parse.statement(` - class Foo { - async foo () {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toEqual( - methodModifiersDoc(['async']), - ); - }); - - test('detects static async functions', () => { - const def = parse.statement(` - class Foo { - static async foo () {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toEqual( - methodModifiersDoc(['static', 'async']), - ); - }); - }); - - describe('returns', () => { - function methodReturnDoc(returnValue) { - return { - name: 'foo', - docblock: null, - modifiers: [], - returns: returnValue, - params: [], - }; - } - - test('returns null if return is not documented', () => { - const def = parse.statement(` - class Foo { - foo () {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toEqual(methodReturnDoc(null)); - }); - - test('extracts flow types', () => { - const def = parse.statement(` - class Foo { - foo (): number {} - } - `); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toEqual( - methodReturnDoc({ - type: { name: 'number' }, - }), - ); - }); - - test('extracts flow types on function assignment', () => { - const def = parse.statement(` - class Foo { - foo = (): number => {} - } - `); - const method = def - .get('body') - .get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toEqual( - methodReturnDoc({ - type: { name: 'number' }, - }), - ); - }); - - test('resolves flow types on imported functions', () => { - const def = parse.statement( - ` - class Foo { - foo = baz - } - import baz from 'baz'; - `, - mockImporter, - ); - const method = def - .get('body') - .get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toEqual( - methodReturnDoc({ - type: { name: 'number' }, - }), - ); - }); - }); - - describe('private', () => { - test('ignores private typescript methods', () => { - const def = parseTypescript.statement( - ` - class Foo { - private foo() {} - } - `, - ); - const method = def.get('body').get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toMatchSnapshot(); - }); - - test('ignores private methods', () => { - const def = parse.statement( - `class Foo { - #foo() {} - }`, - { parserOpts: { plugins: ['classPrivateMethods'] } }, - ); - const method = def - .get('body') - .get('body')[0] as NodePath; - - expect(getMethodDocumentation(method)).toMatchSnapshot(); - }); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getNameOrValue-test.ts b/packages/react-docgen/src/utils/__tests__/getNameOrValue-test.ts deleted file mode 100644 index 63792d2303c..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getNameOrValue-test.ts +++ /dev/null @@ -1,64 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { - QualifiedTypeIdentifier, - TSAsExpression, - TSQualifiedName, - TypeCastExpression, -} from '@babel/types'; -import { parse, parseTypescript } from '../../../tests/utils'; -import getNameOrValue from '../getNameOrValue.js'; -import { describe, expect, test } from 'vitest'; - -describe('getNameOrValue', () => { - test('gets Identifier name', () => { - expect(getNameOrValue(parse.expression('foo'))).toMatchSnapshot(); - }); - - test('gets string literal value', () => { - expect(getNameOrValue(parse.expression('"foo"'))).toMatchSnapshot(); - }); - - test('gets numeric literal value', () => { - expect(getNameOrValue(parse.expression('1'))).toMatchSnapshot(); - }); - - test('gets boolean literal value', () => { - expect(getNameOrValue(parse.expression('true'))).toMatchSnapshot(); - }); - - test('gets null RegExp pattern', () => { - expect(getNameOrValue(parse.expression('/abc?/'))).toMatchSnapshot(); - }); - - test('gets null literal value', () => { - expect(getNameOrValue(parse.expression('null'))).toMatchSnapshot(); - }); - - test('gets TSQualifiedName', () => { - expect( - getNameOrValue( - parseTypescript - .expression('path as x.h') - .get('typeAnnotation.typeName') as NodePath, - ), - ).toMatchSnapshot(); - }); - - test('gets QualifiedTypeIdentifier', () => { - expect( - getNameOrValue( - parse - .expression('path: x.h') - .get( - 'typeAnnotation.typeAnnotation.id', - ) as NodePath, - ), - ).toMatchSnapshot(); - }); - - test('errors on invalid path', () => { - expect(() => - getNameOrValue(parse.statement('function foo(){}')), - ).toThrowErrorMatchingSnapshot(); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getParameterName-test.ts b/packages/react-docgen/src/utils/__tests__/getParameterName-test.ts deleted file mode 100644 index 346ea2b4e0c..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getParameterName-test.ts +++ /dev/null @@ -1,62 +0,0 @@ -import type { - ArrayPattern, - ClassDeclaration, - FunctionExpression, -} from '@babel/types'; -import { parse } from '../../../tests/utils'; -import getParameterName from '../getParameterName.js'; -import { describe, expect, test } from 'vitest'; - -describe('getParameterName', () => { - test('returns the name for a normal parameter', () => { - const def = parse.expression('function(a) {}'); - const param = def.get('params')[0]; - - expect(getParameterName(param)).toEqual('a'); - }); - - test('returns the name for a rest parameter', () => { - const def = parse.expression('function(...a) {}'); - const param = def.get('params')[0]; - - expect(getParameterName(param)).toEqual('...a'); - }); - - test('returns the name for a parameter with a default value', () => { - const def = parse.expression('function(a = 0) {}'); - const param = def.get('params')[0]; - - expect(getParameterName(param)).toEqual('a'); - }); - - test('returns the raw representation for a parameter with object destructuring', () => { - const def = parse.expression('function({a}) {}'); - const param = def.get('params')[0]; - - expect(getParameterName(param)).toEqual('{a}'); - }); - - test('returns the raw representation for a parameter with array destructuring', () => { - const def = parse.expression('function([a]) {}'); - const param = def.get('params')[0]; - - expect(getParameterName(param)).toEqual('[a]'); - }); - - test('throws when passed an invalid path', () => { - // ArrayPattern is wrong, but we test here the throwing, so we are cheating the types - const def = parse.expression('function() {}'); - - expect(() => getParameterName(def)).toThrow(); - }); - - test('handles typescript param property correctly', () => { - const def = parse.expression( - 'class A { constructor(readonly a: any) {}}', - { filename: 'file.ts' }, - ); - const param = def.get('body').get('body')[0].get('params')[0]; - - expect(getParameterName(param)).toEqual('a'); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getPropType-test.ts b/packages/react-docgen/src/utils/__tests__/getPropType-test.ts deleted file mode 100644 index 65e161d06af..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getPropType-test.ts +++ /dev/null @@ -1,645 +0,0 @@ -import type { ExpressionStatement } from '@babel/types'; -import { parse, makeMockImporter } from '../../../tests/utils'; -import getPropType from '../getPropType.js'; -import { describe, expect, test } from 'vitest'; -import type { NodePath } from '@babel/traverse'; - -describe('getPropType', () => { - test('detects simple prop types', () => { - const simplePropTypes = [ - 'array', - 'bool', - 'func', - 'number', - 'object', - 'string', - 'any', - 'element', - 'node', - 'symbol', - 'elementType', - ]; - - simplePropTypes.forEach((type) => - expect(getPropType(parse.expression('React.PropTypes.' + type))).toEqual({ - name: type, - }), - ); - - // It doesn't actually matter what the MemberExpression is - simplePropTypes.forEach((type) => - expect(getPropType(parse.expression('Foo.' + type + '.bar'))).toEqual({ - name: type, - }), - ); - - // Doesn't even have to be a MemberExpression - simplePropTypes.forEach((type) => - expect(getPropType(parse.expression(type))).toEqual({ - name: type, - }), - ); - }); - - test('detects complex prop types', () => { - expect(getPropType(parse.expression('oneOf(["foo", "bar"])'))).toEqual({ - name: 'enum', - value: [ - { value: '"foo"', computed: false }, - { value: '"bar"', computed: false }, - ], - }); - - // line comments are ignored - expect( - getPropType(parse.expression('oneOf(["foo", // baz\n"bar"])')), - ).toEqual({ - name: 'enum', - value: [ - { value: '"foo"', computed: false }, - { value: '"bar"', computed: false }, - ], - }); - - expect(getPropType(parse.expression('oneOfType([number, bool])'))).toEqual({ - name: 'union', - value: [{ name: 'number' }, { name: 'bool' }], - }); - - // custom type - expect(getPropType(parse.expression('oneOfType([foo])'))).toEqual({ - name: 'union', - value: [{ name: 'custom', raw: 'foo' }], - }); - - expect(getPropType(parse.expression('instanceOf(Foo)'))).toEqual({ - name: 'instanceOf', - value: 'Foo', - }); - - expect(getPropType(parse.expression('arrayOf(string)'))).toEqual({ - name: 'arrayOf', - value: { name: 'string' }, - }); - - expect(getPropType(parse.expression('objectOf(string)'))).toEqual({ - name: 'objectOf', - value: { name: 'string' }, - }); - - expect( - getPropType(parse.expression('shape({foo: string, bar: bool})')), - ).toEqual({ - name: 'shape', - value: { - foo: { - name: 'string', - required: false, - }, - bar: { - name: 'bool', - required: false, - }, - }, - }); - - expect( - getPropType(parse.expression('exact({foo: string, bar: bool})')), - ).toEqual({ - name: 'exact', - value: { - foo: { - name: 'string', - required: false, - }, - bar: { - name: 'bool', - required: false, - }, - }, - }); - - // custom - expect(getPropType(parse.expression('shape({foo: xyz})'))).toEqual({ - name: 'shape', - value: { - foo: { - name: 'custom', - raw: 'xyz', - required: false, - }, - }, - }); - - // custom - expect(getPropType(parse.expression('exact({foo: xyz})'))).toEqual({ - name: 'exact', - value: { - foo: { - name: 'custom', - raw: 'xyz', - required: false, - }, - }, - }); - - // computed - expect(getPropType(parse.expression('shape(Child.propTypes)'))).toEqual({ - name: 'shape', - value: 'Child.propTypes', - computed: true, - }); - - // computed - expect(getPropType(parse.expression('exact(Child.propTypes)'))).toEqual({ - name: 'exact', - value: 'Child.propTypes', - computed: true, - }); - }); - - describe('resolve identifier to their values', () => { - const mockImporter = makeMockImporter({ - shape: (stmt) => - stmt(` - export default {bar: PropTypes.string}; - `).get('declaration'), - - types: (stmt) => - stmt(` - export default ["foo", "bar"]; - `).get('declaration'), - - foo: (stmt) => - stmt(` - export default "foo"; - `).get('declaration'), - - bar: (stmt) => - stmt(` - export default "bar"; - `).get('declaration'), - - obj: (stmt) => - stmt(` - export default { FOO: "foo", BAR: "bar" }; - `).get('declaration'), - - arr: (stmt) => - stmt(` - export default ["foo", "bar"]; - `).get('declaration'), - - keys: (stmt) => - stmt(` - import obj from 'obj'; - export default Object.keys(obj); - `).get('declaration'), - - values: (stmt) => - stmt(` - import obj from 'obj'; - export default Object.values(obj); - `).get('declaration'), - }); - - test('resolves variables to their values', () => { - const propTypeExpression = parse - .statement( - ` - PropTypes.shape(shape); - var shape = {bar: PropTypes.string}; - `, - ) - .get('expression'); - - expect(getPropType(propTypeExpression)).toMatchSnapshot(); - }); - - test('resolves imported variables to their values', () => { - const propTypeExpression = parse - .statement( - ` - PropTypes.shape(shape); - import shape from 'shape'; - `, - mockImporter, - ) - .get('expression'); - - expect(getPropType(propTypeExpression)).toMatchSnapshot(); - }); - - test('resolves simple identifier to their initialization value', () => { - const propTypeIdentifier = parse - .statement( - ` - PropTypes.oneOf(TYPES); - var TYPES = ["foo", "bar"]; - `, - ) - .get('expression'); - - expect(getPropType(propTypeIdentifier)).toMatchSnapshot(); - }); - - test('resolves importer identifier to initialization value', () => { - const propTypeIdentifier = parse - .statement( - ` - PropTypes.oneOf(TYPES); - import TYPES from 'types'; - `, - mockImporter, - ) - .get('expression'); - - expect(getPropType(propTypeIdentifier)).toMatchSnapshot(); - }); - - test('resolves simple identifier to their initialization value in array', () => { - const identifierInsideArray = parse - .statement( - ` - PropTypes.oneOf([FOO, BAR]); - var FOO = "foo"; - var BAR = "bar"; - `, - ) - .get('expression'); - - expect(getPropType(identifierInsideArray)).toMatchSnapshot(); - }); - - test('resolves imported identifier to their initialization value in array', () => { - const identifierInsideArray = parse - .statement( - ` - PropTypes.oneOf([FOO, BAR]); - import FOO from 'foo'; - import BAR from 'bar'; - `, - mockImporter, - ) - .get('expression'); - - expect(getPropType(identifierInsideArray)).toMatchSnapshot(); - }); - - test('handles unresolved imported identifier to their initialization value in array', () => { - const identifierInsideArray = parse - .statement( - ` - PropTypes.oneOf([FOO, BAR]); - import FOO from 'foo'; - import BAR from 'bar'; - `, - ) - .get('expression'); - - expect(getPropType(identifierInsideArray)).toMatchSnapshot(); - }); - - test('handles unresolved named imported identifier to their initialization value in array', () => { - const identifierInsideArray = parse - .statement( - ` - PropTypes.oneOf([FOO, BAR]); - import { FOO } from 'foo'; - import { BAR } from 'bar'; - `, - ) - .get('expression'); - - expect(getPropType(identifierInsideArray)).toMatchSnapshot(); - }); - - test('resolves memberExpressions', () => { - const propTypeExpression = parse - .statement( - ` - PropTypes.oneOf([TYPES.FOO, TYPES.BAR]); - var TYPES = { FOO: "foo", BAR: "bar" }; - `, - ) - .get('expression'); - - expect(getPropType(propTypeExpression)).toMatchSnapshot(); - }); - - test('resolves memberExpressions from imported objects', () => { - const propTypeExpression = parse - .statement( - ` - PropTypes.oneOf([TYPES.FOO, TYPES.BAR]); - import TYPES from 'obj'; - `, - mockImporter, - ) - .get('expression'); - - expect(getPropType(propTypeExpression)).toMatchSnapshot(); - }); - - test('correctly resolves SpreadElements in arrays', () => { - const propTypeExpression = parse - .statement( - ` - PropTypes.oneOf([...TYPES]); - var TYPES = ["foo", "bar"]; - `, - ) - .get('expression'); - - expect(getPropType(propTypeExpression)).toMatchSnapshot(); - }); - - test('correctly resolves SpreadElements in arrays from imported values', () => { - const propTypeExpression = parse - .statement( - ` - PropTypes.oneOf([...TYPES]); - import TYPES from 'arr'; - `, - mockImporter, - ) - .get('expression'); - - expect(getPropType(propTypeExpression)).toMatchSnapshot(); - }); - - test('correctly resolves nested SpreadElements in arrays', () => { - const propTypeExpression = parse - .statement( - ` - PropTypes.oneOf([...TYPES]); - var TYPES = ["foo", ...TYPES2]; - var TYPES2 = ["bar"]; - `, - ) - .get('expression'); - - expect(getPropType(propTypeExpression)).toMatchSnapshot(); - }); - - test('does resolve object keys values', () => { - const propTypeExpression = parse - .statement( - ` - PropTypes.oneOf(Object.keys(TYPES)); - var TYPES = { FOO: "foo", BAR: "bar" }; - `, - ) - .get('expression'); - - expect(getPropType(propTypeExpression)).toMatchSnapshot(); - }); - - test('resolves values from imported Object.keys call', () => { - const propTypeExpression = parse - .statement( - ` - PropTypes.oneOf(keys); - import keys from 'keys'; - `, - mockImporter, - ) - .get('expression'); - - expect(getPropType(propTypeExpression)).toMatchSnapshot(); - }); - - test('does resolve object values', () => { - const propTypeExpression = parse - .statement( - ` - PropTypes.oneOf(Object.values(TYPES)); - var TYPES = { FOO: "foo", BAR: "bar" }; - `, - ) - .get('expression'); - - expect(getPropType(propTypeExpression)).toMatchSnapshot(); - }); - - test('resolves values from imported Object.values call', () => { - const propTypeExpression = parse - .statement( - ` - PropTypes.oneOf(values); - import values from 'values'; - `, - mockImporter, - ) - .get('expression'); - - expect(getPropType(propTypeExpression)).toMatchSnapshot(); - }); - - test('resolves value constants from imported objects', () => { - const propTypeExpression = parse - .statement( - ` - const values = { - FOO: consts.FOO, BAR: consts.BAR - } - PropTypes.oneOf(Object.values(values)); - import consts from 'obj'; - `, - mockImporter, - 1, - ) - .get('expression'); - - expect(getPropType(propTypeExpression)).toMatchSnapshot(); - }); - - test('handles unresolved value constants from imported objects', () => { - const propTypeExpression = parse - .statement( - ` - const values = { - FOO: consts.FOO, BAR: consts.BAR - } - PropTypes.oneOf(Object.values(values)); - import consts from 'obj'; - `, - 1, - ) - .get('expression'); - - expect(getPropType(propTypeExpression)).toMatchSnapshot(); - }); - - test('does not resolve external values without proper importer', () => { - const propTypeExpression = parse - .statement( - ` - PropTypes.oneOf(TYPES); - import { TYPES } from './foo.js'; - `, - ) - .get('expression'); - - expect(getPropType(propTypeExpression)).toMatchSnapshot(); - }); - }); - - test('detects custom validation functions for function', () => { - expect(getPropType(parse.expression('(function() {})'))).toMatchSnapshot(); - }); - - test('detects custom validation functions for arrow function', () => { - expect(getPropType(parse.expression('() => {}'))).toMatchSnapshot(); - }); - - test('detects descriptions on nested types in arrayOf', () => { - expect( - getPropType( - parse.expression(`arrayOf( - /** - * test2 - */ - string - )`), - ), - ).toMatchSnapshot(); - }); - - test('detects descriptions on nested types in objectOf', () => { - expect( - getPropType( - parse.expression(`objectOf( - /** - * test2 - */ - string - )`), - ), - ).toMatchSnapshot(); - }); - - test('detects descriptions on nested types in shapes', () => { - expect( - getPropType( - parse.expression(`shape({ - /** - * test1 - */ - foo: string, - /** - * test2 - */ - bar: bool - })`), - ), - ).toMatchSnapshot(); - }); - - test('detects required notations of nested types in shapes', () => { - expect( - getPropType( - parse.expression(`shape({ - foo: string.isRequired, - bar: bool - })`), - ), - ).toMatchSnapshot(); - }); - - test('detects descriptions on nested types in exacts', () => { - expect( - getPropType( - parse.expression(`exact({ - /** - * test1 - */ - foo: string, - /** - * test2 - */ - bar: bool - })`), - ), - ).toMatchSnapshot(); - }); - - test('detects required notations of nested types in exacts', () => { - expect( - getPropType( - parse.expression(`exact({ - foo: string.isRequired, - bar: bool - })`), - ), - ).toMatchSnapshot(); - }); - - test('handles computed properties', () => { - expect( - getPropType( - parse.expression(`exact({ - [foo]: string.isRequired, - bar: bool - })`), - ), - ).toMatchSnapshot(); - }); - - test('ignores complex computed properties', () => { - expect( - getPropType( - parse.expression(`exact({ - [() => {}]: string.isRequired, - bar: bool - })`), - ), - ).toMatchSnapshot(); - }); - - test('works with cyclic references in shape', () => { - expect( - getPropType( - parse - .statementLast( - `const Component = () => {} - Component.propTypes = { - foo: shape(Component.propTypes) - }`, - ) - .get('expression.right.properties.0.value') as NodePath, - ), - ).toMatchSnapshot(); - }); - - test('works with cyclic references in shape and required', () => { - expect( - getPropType( - parse - .statementLast( - `const Component = () => {} - Component.propTypes = { - foo: shape(Component.propTypes).isRequired - }`, - ) - .get('expression.right.properties.0.value') as NodePath, - ), - ).toMatchSnapshot(); - }); - - test('works with missing argument', () => { - expect( - getPropType( - parse - .statementLast( - `const Component = () => {} - const MyShape = { foo: shape() } - Component.propTypes = { - foo: shape(MyShape) - }`, - ) - .get('expression.right.properties.0.value') as NodePath, - ), - ).toMatchSnapshot(); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getPropertyName-test.ts b/packages/react-docgen/src/utils/__tests__/getPropertyName-test.ts deleted file mode 100644 index 81f22ad46f0..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getPropertyName-test.ts +++ /dev/null @@ -1,130 +0,0 @@ -import type { ObjectExpression, TypeCastExpression } from '@babel/types'; -import { parse, makeMockImporter } from '../../../tests/utils'; -import getPropertyName from '../getPropertyName.js'; -import { describe, expect, test } from 'vitest'; - -describe('getPropertyName', () => { - const mockImporter = makeMockImporter({ - foo: (stmtLast) => - stmtLast(` - export default "name"; - `).get('declaration'), - - bar: (stmtLast) => - stmtLast(` - export default { baz: "name" }; - `).get('declaration'), - }); - - test('returns the name for a normal property', () => { - const def = parse.expression('{ foo: 1 }'); - const param = def.get('properties')[0]; - - expect(getPropertyName(param)).toBe('foo'); - }); - - test('returns the name of a object type spread property', () => { - const def = parse.expression('(a: { ...foo })'); - const param = def - .get('typeAnnotation') - .get('typeAnnotation') - .get('properties')[0]; - - expect(getPropertyName(param)).toBe('foo'); - }); - - test('returns the qualified name of a object type spread property', () => { - const def = parse.expression('(a: { ...foo.bub })'); - const param = def - .get('typeAnnotation') - .get('typeAnnotation') - .get('properties')[0]; - - expect(getPropertyName(param)).toBe('foo.bub'); - }); - - test('creates name for computed properties', () => { - const def = parse.expression('{ [foo]: 21 }'); - const param = def.get('properties')[0]; - - expect(getPropertyName(param)).toBe('@computed#foo'); - }); - - test('creates name for computed properties from string', () => { - const def = parse.expression('{ ["foo"]: 21 }'); - const param = def.get('properties')[0]; - - expect(getPropertyName(param)).toBe('foo'); - }); - - test('creates name for computed properties from int', () => { - const def = parse.expression('{ [31]: 21 }'); - const param = def.get('properties')[0]; - - expect(getPropertyName(param)).toBe('31'); - }); - - test('returns null for computed properties from regex', () => { - const def = parse.expression('{ [/31/]: 21 }'); - const param = def.get('properties')[0]; - - expect(getPropertyName(param)).toBe(null); - }); - - test('returns null for to complex computed properties', () => { - const def = parse.expression('{ [() => {}]: 21 }'); - const param = def.get('properties')[0]; - - expect(getPropertyName(param)).toBe(null); - }); - - test('resolves simple variables', () => { - const def = parse.expressionLast(` - const foo = "name"; - - ({ [foo]: 21 }); - `); - const param = def.get('properties')[0]; - - expect(getPropertyName(param)).toBe('name'); - }); - - test('resolves imported variables', () => { - const def = parse.expressionLast( - ` - import foo from 'foo'; - - ({ [foo]: 21 }); - `, - mockImporter, - ); - const param = def.get('properties')[0]; - - expect(getPropertyName(param)).toBe('name'); - }); - - test('resolves simple member expressions', () => { - const def = parse.expressionLast(` - const a = { foo: "name" }; - - ({ [a.foo]: 21 }); - `); - const param = def.get('properties')[0]; - - expect(getPropertyName(param)).toBe('name'); - }); - - test('resolves imported member expressions', () => { - const def = parse.expressionLast( - ` - import bar from 'bar'; - - ({ [bar.baz]: 21 }); - `, - mockImporter, - ); - const param = def.get('properties')[0]; - - expect(getPropertyName(param)).toBe('name'); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getPropertyValuePath-test.ts b/packages/react-docgen/src/utils/__tests__/getPropertyValuePath-test.ts deleted file mode 100644 index aa4450b0652..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getPropertyValuePath-test.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { ExpressionStatement, ObjectExpression } from '@babel/types'; -import { parse, makeMockImporter } from '../../../tests/utils'; -import getPropertyValuePath from '../getPropertyValuePath.js'; -import { describe, expect, test } from 'vitest'; - -describe('getPropertyValuePath', () => { - const mockImporter = makeMockImporter({ - bar: (stmt) => stmt(`export default 'bar';`).get('declaration'), - }); - - test('returns the value path if the property exists', () => { - const objectExpressionPath = parse - .statement('({foo: 21, bar: 42})') - .get('expression') as NodePath; - - expect(getPropertyValuePath(objectExpressionPath, 'bar')).toBe( - objectExpressionPath.get('properties')[1].get('value'), - ); - }); - - test('returns the value path for a computed property in scope', () => { - const objectExpressionPath = parse - .statement( - ` - ({foo: 21, [a]: 42}); - var a = 'bar'; - `, - ) - .get('expression') as NodePath; - - expect(getPropertyValuePath(objectExpressionPath, 'bar')).toBe( - objectExpressionPath.get('properties')[1].get('value'), - ); - }); - - test('returns undefined if the property does not exist', () => { - const objectExpressionPath = parse - .statement('({foo: 21, bar: 42})') - .get('expression') as NodePath; - - expect(getPropertyValuePath(objectExpressionPath, 'baz')).toBeNull(); - }); - - test('returns the value path for a computed property that was imported', () => { - const objectExpressionPath = parse - .statement( - ` - ({foo: 21, [a]: 42}); - import a from 'bar'; - `, - mockImporter, - ) - .get('expression') as NodePath; - - expect(getPropertyValuePath(objectExpressionPath, 'bar')).toBe( - objectExpressionPath.get('properties')[1].get('value'), - ); - }); - - test('returns ObjectMethod directly', () => { - const objectExpressionPath = parse - .statement('({ foo(){} })') - .get('expression') as NodePath; - - expect(getPropertyValuePath(objectExpressionPath, 'foo')).toBe( - objectExpressionPath.get('properties')[0], - ); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getTSType-test.ts b/packages/react-docgen/src/utils/__tests__/getTSType-test.ts deleted file mode 100644 index 0413d2b8503..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getTSType-test.ts +++ /dev/null @@ -1,723 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { - Declaration, - ExportNamedDeclaration, - TSInterfaceDeclaration, - TSTypeAnnotation, - TypeScript, - VariableDeclaration, -} from '@babel/types'; -import { - parseTypescript, - makeMockImporter, - noopImporter, -} from '../../../tests/utils'; -import type { Importer } from '../../importer'; -import getTSType from '../getTSType.js'; -import { describe, expect, test } from 'vitest'; - -function typeAlias( - stmt: string, - importer: Importer = noopImporter, -): NodePath { - return parseTypescript - .statement(stmt, importer) - .get( - 'declarations.0.id.typeAnnotation.typeAnnotation', - ) as NodePath; -} - -const mockImporter = makeMockImporter({ - abc: (stmtLast) => - stmtLast(`export type abc = number;`, true).get( - 'declaration', - ) as NodePath, - - def: (stmtLast) => - stmtLast(`export type def = boolean;`, true).get( - 'declaration', - ) as NodePath, - - xyz: (stmtLast) => - stmtLast(`export type xyz = string;`, true).get( - 'declaration', - ) as NodePath, - - barbaz: (stmtLast) => - stmtLast( - `export type barbaz = "bar" | "baz";`, - true, - ).get('declaration') as NodePath, - - recTup: (stmtLast) => - stmtLast( - `import { abc } from 'abc'; - import { xyz } from 'xyz'; - export type recTup = [abc, xyz];`, - true, - ).get('declaration') as NodePath, - - obj: (stmtLast) => - stmtLast( - `export type A = { x: string };`, - true, - ).get('declaration') as NodePath, - - MyType: (stmtLast) => - stmtLast( - `import { xyz } from 'xyz'; - export type MyType = { a: number, b: xyz };`, - true, - ).get('declaration') as NodePath, - - MyGenericType: (stmtLast) => - stmtLast( - `export type MyGenericType = { a: T, b: Array };`, - true, - ).get('declaration') as NodePath, - - fruits: (stmtLast) => - stmtLast( - ` - export default { - 'apple': '🍎', - 'banana': '🍌', - }; - `, - ).get('declaration'), -}); - -describe('getTSType', () => { - test('detects simple types', () => { - const simplePropTypes = [ - 'string', - 'number', - 'boolean', - 'symbol', - 'object', - 'any', - 'unknown', - 'null', - 'undefined', - 'void', - 'Object', - 'Function', - 'Boolean', - 'String', - 'Number', - ]; - - simplePropTypes.forEach((type) => { - const typePath = typeAlias(`let x: ${type};`); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - }); - - describe('literal types', () => { - const literalTypes = ['"foo"', 1234, true, -1, '`foo`']; - - literalTypes.forEach((value) => { - test(`detects ${value}`, () => { - const typePath = typeAlias(`let x: ${value};`); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - }); - }); - - test('detects external type', () => { - const typePath = typeAlias('let x: xyz;'); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves external type', () => { - const typePath = typeAlias( - ` - let x: xyz; - import { xyz } from 'xyz'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects array type shorthand', () => { - const typePath = typeAlias('let x: number[];'); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects array type', () => { - const typePath = typeAlias('let x: Array;'); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects array type with multiple types', () => { - const typePath = typeAlias('let x: Array;'); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves imported types used for arrays', () => { - let typePath = typeAlias( - ` - let x: xyz[]; - import { xyz } from 'xyz'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - - typePath = typeAlias( - ` - let x: Array; - import { xyz } from 'xyz'; - `, - mockImporter, - ); - expect(getTSType(typePath)).toMatchSnapshot(); - - typePath = typeAlias( - ` - let x: Array; - import { xyz } from 'xyz'; - `, - mockImporter, - ); - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects class type', () => { - const typePath = typeAlias('let x: Class;'); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves imported subtype for class type', () => { - const typePath = typeAlias( - ` - let x: Class; - import { xyz } from 'xyz' - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects function type with subtype', () => { - const typePath = typeAlias('let x: Function;'); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves imported subtype for function type', () => { - const typePath = typeAlias( - ` - let x: Function; - import { xyz } from 'xyz'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects object types', () => { - const typePath = typeAlias('let x: { a: string, b?: xyz };'); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves imported types for object property types', () => { - const typePath = typeAlias( - ` - let x: { a: number, b?: xyz }; - import { xyz } from 'xyz'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects union type', () => { - const typePath = typeAlias('let x: string | xyz | "foo" | void;'); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves imported types within union type', () => { - const typePath = typeAlias( - ` - let x: string | barbaz | "foo" | void; - import { barbaz } from 'barbaz'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects intersection type', () => { - const typePath = typeAlias('let x: string & xyz & "foo" & void;'); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves imported types within intersection type', () => { - const typePath = typeAlias( - ` - let x: string & barbaz & "foo" & void; - import { barbaz } from 'barbaz'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects function signature type', () => { - const typePath = typeAlias( - 'let x: (p1: number, p2: string, ...rest: Array) => boolean;', - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects function signature type with `this` parameter', () => { - const typePath = typeAlias('let x: (this: Foo, p1: number) => boolean;'); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects function signature type with object and array pattern', () => { - const typePath = typeAlias( - 'let x: ({ x }: { x: number }, [ f,s ]: Array) => boolean;', - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects callable signature type', () => { - const typePath = typeAlias( - 'let x: { (str: string): string, token: string };', - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves function signature types with imported types', () => { - let typePath = typeAlias( - ` - let x: (p1: abc, p2: xyz, ...rest: Array) => def; - import { abc } from 'abc'; - import { def } from 'def'; - import { xyz } from 'xyz'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - - typePath = typeAlias( - ` - let x: (this: xyz, p1: number) => boolean; - import { xyz } from 'xyz'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - - typePath = typeAlias( - ` - let x: { (str: xyz): abc, token: def }; - import { abc } from 'abc'; - import { def } from 'def'; - import { xyz } from 'xyz'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects map signature', () => { - const typePath = typeAlias( - 'let x: { [key: string]: number, [key: "xl"]: string, token: "a" | "b" };', - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves imported types in map signature', () => { - const typePath = typeAlias( - ` - let x: { [key: xyz]: abc, [key: "xl"]: xyz, token: barbaz }; - import { abc } from 'abc'; - import { xyz } from 'xyz'; - import { barbaz } from 'barbaz'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects tuple signature', () => { - const typePath = typeAlias('let x: [string, number];'); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects tuple in union signature', () => { - const typePath = typeAlias('let x: [string, number] | [number, string];'); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves imported types in tuple signatures', () => { - let typePath = typeAlias( - ` - let x: [xyz, abc]; - import { abc } from 'abc'; - import { xyz } from 'xyz'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - - typePath = typeAlias( - ` - let x: [xyz, abc] | recTup; - import { abc } from 'abc'; - import { xyz } from 'xyz'; - import { recTup } from 'recTup'; - `, - mockImporter, - ); - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('detects indexed access', () => { - const typePath = typeAlias(` - var x: A["x"] = 2; - - interface A { x: string }; - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves indexed access', () => { - const typePath = typeAlias(` - var x: A["x"] = 2; - - type A = { x: string }; - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves indexed access of array', () => { - const typePath = parseTypescript - .statement( - ` - var x: typeof STRING_VALS[number]; - - const STRING_VALS = [ - 'one', - 'two', - 'three' - ]; - `, - ) - .get('declarations')[0] - .get('id') - .get('typeAnnotation') - .get('typeAnnotation'); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('can resolve indexed access to imported type', () => { - const typePath = typeAlias( - ` - var x: A["x"] = 2; - import { A } from 'obj'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves types in scope', () => { - const typePath = typeAlias(` - var x: MyType = 2; - - type MyType = string; - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('handles typeof type', () => { - const typePath = typeAlias(` - var x: typeof MyType = {}; - - type MyType = { a: string, b: xyz }; - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('handles typeof qualified type', () => { - const typePath = typeAlias(` - var x: typeof MyType.a = {}; - - type MyType = { a: string, b: xyz }; - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves typeof of imported type', () => { - const typePath = typeAlias( - ` - var x: typeof MyType = {}; - import { MyType } from 'MyType'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves typeof of import type', () => { - const typePath = typeAlias( - "var x: typeof import('MyType') = {};", - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('handles qualified type identifiers', () => { - const typePath = typeAlias(` - var x: MyType.x = {}; - - type MyType = { a: string, b: xyz }; - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('handles qualified type identifiers with params', () => { - const typePath = typeAlias(` - var x: MyType.x = {}; - - type MyType = { a: string, b: xyz }; - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('handles generic types', () => { - const typePath = typeAlias(` - var x: MyType = {}; - - type MyType = { a: T, b: Array }; - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves imported types that need subtypes', () => { - const typePath = typeAlias( - ` - var x: MyGenericType = {}; - import { MyGenericType } from 'MyGenericType'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('handles mapped types', () => { - const typePath = typeAlias(` - var x: { [key in 'x' | 'y']: boolean}; - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves imported types applied to mapped types', () => { - const typePath = typeAlias( - ` - var x: { [key in barbaz]: boolean}; - import { barbaz } from 'barbaz'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - describe('React types', () => { - const types = [ - 'React.Node', - 'React.Key', - 'React.ElementType', - 'React.ChildrenArray', - 'React.Element', - 'React.Ref', - 'React.ElementProps', - 'React.ElementRef', - 'React.ComponentType', - 'React.StatelessFunctionalComponent', - ]; - - types.forEach((type) => { - test(type, () => { - const typePath = typeAlias(` - var x: ${type} = 2; - - type Props = { x: string }; - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - }); - }); - - test('resolves keyof to union', () => { - const typePath = typeAlias(` - var x: keyof typeof CONTENTS = 2; - const CONTENTS = { - 'apple': '🍎', - 'banana': '🍌', - }; - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves keyof with imported types', () => { - const typePath = typeAlias( - ` - var x: keyof typeof CONTENTS = 2; - import CONTENTS from 'fruits'; - `, - mockImporter, - ); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('resolves keyof with inline object to union', () => { - const typePath = typeAlias(` - var x: keyof { apple: string, banana: string } = 2; - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('handles multiple references to one type', () => { - const typePath = typeAlias(` - let action: { a: Action, b: Action }; - type Action = {}; - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('handles generics of the same Name', () => { - const typePath = parseTypescript - .statement( - ` - interface Props { - baz: Foo - } - - type Foo = Bar - `, - ) - .get('body') - .get('body')[0] - .get('typeAnnotation') as NodePath; - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('handles self-referencing type cycles', () => { - const typePath = typeAlias(` - let action: Action; - type Action = { subAction: Action }; - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('handles long type cycles', () => { - const typePath = typeAlias(` - let action: Action; - type Action = { subAction: SubAction }; - type SubAction = { subAction: SubSubAction }; - type SubSubAction = { subAction: SubSubSubAction }; - type SubSubSubAction = { rootAction: Action }; - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('handles mapped type', () => { - const typePath = typeAlias(` - let action: OptionsFlags; - type OptionsFlags = { - [Property in keyof Type]: number; - }; - interface X { - foo: string - } - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('handles mapped type with implicit any', () => { - const typePath = typeAlias(` - let action: OptionsFlags; - type OptionsFlags = { - [Property in keyof Type]; - }; - interface X { - foo: string - } - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); - - test('handles mapped type without typeParam', () => { - const typePath = typeAlias(` - let action: OptionsFlags; - type OptionsFlags = { - [Property in keyof X]: string; - }; - interface X { - foo: string - } - `); - - expect(getTSType(typePath)).toMatchSnapshot(); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getTypeAnnotation-test.ts b/packages/react-docgen/src/utils/__tests__/getTypeAnnotation-test.ts deleted file mode 100644 index c45ca428e30..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getTypeAnnotation-test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { TypeCastExpression } from '@babel/types'; -import { parse } from '../../../tests/utils'; -import getTypeAnnotation from '../getTypeAnnotation.js'; -import { describe, expect, test } from 'vitest'; - -describe('getTypeAnnotation', () => { - test('detects simple type', () => { - const path = parse.expression('x: xyz'); - - expect(getTypeAnnotation(path)).toEqual( - path.get('typeAnnotation').get('typeAnnotation'), - ); - }); - - test('does not fail if no type', () => { - const path = parse.expression('x = 0'); - - expect(getTypeAnnotation(path)).toEqual(null); - }); - - test('stops at first nested type', () => { - const path = parse.expression('x: ?xyz'); - - expect(getTypeAnnotation(path)).toEqual( - path.get('typeAnnotation').get('typeAnnotation'), - ); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getTypeFromReactComponent-test.ts b/packages/react-docgen/src/utils/__tests__/getTypeFromReactComponent-test.ts deleted file mode 100644 index 47e6d26836d..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getTypeFromReactComponent-test.ts +++ /dev/null @@ -1,219 +0,0 @@ -import type { - ArrowFunctionExpression, - ClassDeclaration, - VariableDeclaration, -} from '@babel/types'; -import { parse, parseTypescript } from '../../../tests/utils'; -import getTypeFromReactComponent from '../getTypeFromReactComponent.js'; -import { describe, expect, test } from 'vitest'; -import type { NodePath } from '@babel/traverse'; - -describe('getTypeFromReactComponent', () => { - test('handles no stateless props', () => { - const path = parseTypescript - .statementLast(`const x = () => {}`) - .get('declarations')[0] - .get('init') as NodePath; - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - - test('handles no class props', () => { - const path = parseTypescript.statementLast( - `import React from 'react'; - class X extends React.Component { - render() {} - }`, - ); - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - - describe('TypeScript', () => { - describe('stateless', () => { - test('finds param type annotation', () => { - const path = parseTypescript - .statementLast(`const x = (props: Props) => {}`) - .get('declarations')[0] - .get('init') as NodePath; - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - - test('finds wrapped param type annotation', () => { - const path = parseTypescript - .statementLast( - `import React from 'react'; - const x = (props: React.PropsWithChildren) => {}`, - ) - .get('declarations')[0] - .get('init') as NodePath; - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - - test('finds generic forwardRef type annotation', () => { - const path = parseTypescript - .statementLast( - `import React from 'react'; - const x = React.forwardRef>((props, ref) => {})`, - ) - .get('declarations')[0] - .get('init') as NodePath; - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - - test('does not find generic forwardRef type annotation on typo', () => { - const path = parseTypescript - .statementLast( - `import React from 'react'; - const x = React.backwardRef>((props, ref) => {})`, - ) - .get('declarations')[0] - .get('init') as NodePath; - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - - test('finds param inline type', () => { - const path = parseTypescript - .statementLast( - `const x = (props: { prop: string }) => {}`, - ) - .get('declarations')[0] - .get('init') as NodePath; - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - - describe.each([ - 'FunctionComponent', - 'FC', - 'VoidFunctionComponent', - 'VFC', - ])('finds variable type annotation (%s)', (name) => { - test('with MemberExpression', () => { - const path = parseTypescript - .statementLast( - `import React from 'react'; - const x: React.${name} = (props) => {}`, - ) - .get('declarations')[0] - .get('init') as NodePath; - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - - test('with named import', () => { - const path = parseTypescript - .statementLast( - `import { ${name} } from 'react'; - const x: ${name} = (props) => {}`, - ) - .get('declarations')[0] - .get('init') as NodePath; - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - }); - - test('finds multiple variable type annotation', () => { - const path = parseTypescript - .statementLast( - `import React from 'react'; - const x: React.FC = (props: Props) => {}`, - ) - .get('declarations')[0] - .get('init') as NodePath; - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - }); - - describe('classes', () => { - test('finds props type in params', () => { - const path = parseTypescript.statementLast( - `import React from 'react'; - class X extends React.Component { - render() {} - }`, - ); - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - - test('finds props type in properties', () => { - const path = parseTypescript.statementLast( - `import React from 'react'; - class X extends React.Component { - props: Props; - render() {} - }`, - ); - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - }); - }); - - describe('Flow', () => { - describe('stateless', () => { - test('finds param type annotation', () => { - const path = parse - .statementLast(`const x = (props: Props) => {}`) - .get('declarations')[0] - .get('init') as NodePath; - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - - test('finds param inline type', () => { - const path = parse - .statementLast( - `const x = (props: { prop: string }) => {}`, - ) - .get('declarations')[0] - .get('init') as NodePath; - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - }); - - describe('classes', () => { - test('finds props type in new params', () => { - const path = parse.statementLast( - `import React from 'react'; - class X extends React.Component { - render() {} - }`, - ); - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - - test('finds props type in old params', () => { - const path = parse.statementLast( - `import React from 'react'; - class X extends React.Component { - render() {} - }`, - ); - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - - test('finds props type in properties', () => { - const path = parse.statementLast( - `import React from 'react'; - class X extends React.Component { - props: Props; - render() {} - }`, - ); - - expect(getTypeFromReactComponent(path)).toMatchSnapshot(); - }); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/getTypeParameters-test.ts b/packages/react-docgen/src/utils/__tests__/getTypeParameters-test.ts deleted file mode 100644 index e715c21effd..00000000000 --- a/packages/react-docgen/src/utils/__tests__/getTypeParameters-test.ts +++ /dev/null @@ -1,61 +0,0 @@ -import type { - TSTypeAliasDeclaration, - TSTypeParameterDeclaration, - TSTypeParameterInstantiation, - TypeAlias, - TypeParameterDeclaration, - TypeParameterInstantiation, -} from '@babel/types'; -import { parse, parseTypescript } from '../../../tests/utils'; -import getTypeParameters from '../getTypeParameters.js'; -import { describe, expect, test } from 'vitest'; -import type { NodePath } from '@babel/traverse'; - -describe('getTypeParameters', () => { - describe('TypeScript', () => { - test('detects simple type', () => { - const path = - parseTypescript.statement('type x = y'); - - expect( - getTypeParameters( - path.get('typeParameters') as NodePath, - path - .get('typeAnnotation') - .get('typeParameters') as NodePath, - null, - ), - ).toMatchSnapshot(); - }); - test('detects default', () => { - const path = parseTypescript.statement( - 'type x = y;', - ); - - expect( - getTypeParameters( - path.get('typeParameters') as NodePath, - path - .get('typeAnnotation') - .get('typeParameters') as NodePath, - null, - ), - ).toMatchSnapshot(); - }); - }); - describe('Flow', () => { - test('detects simple type', () => { - const path = parse.statement('type x = y'); - - expect( - getTypeParameters( - path.get('typeParameters') as NodePath, - path - .get('right') - .get('typeParameters') as NodePath, - null, - ), - ).toMatchSnapshot(); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/isDestructuringAssignment-test.ts b/packages/react-docgen/src/utils/__tests__/isDestructuringAssignment-test.ts deleted file mode 100644 index 46ab379a3b0..00000000000 --- a/packages/react-docgen/src/utils/__tests__/isDestructuringAssignment-test.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { Node } from '@babel/types'; -import { parse } from '../../../tests/utils'; -import isDestructuringAssignment from '../isDestructuringAssignment.js'; -import { describe, expect, test } from 'vitest'; - -describe('isDestructuringAssignment', () => { - test('detects destructuring', () => { - const def = parse(` - var { Component } = require('react'); - `).get('body.0.declarations.0.id.properties.0') as NodePath; - - expect(isDestructuringAssignment(def, 'Component')).toBe(true); - }); - - test('fails if name does not match', () => { - const def = parse(` - var { Component } = require('react'); - `).get('body.0.declarations.0.id.properties.0') as NodePath; - - expect(isDestructuringAssignment(def, 'Component2')).toBe(false); - }); - - test('detects destructuring with alias', () => { - const def = parse(` - var { Component: C } = require('react'); - `).get('body.0.declarations.0.id.properties.0') as NodePath; - - expect(isDestructuringAssignment(def, 'Component')).toBe(true); - }); - - test('fails if name does not match with alias', () => { - const def = parse(` - var { Component: C } = require('react'); - `).get('body.0.declarations.0.id.properties.0') as NodePath; - - expect(isDestructuringAssignment(def, 'Component2')).toBe(false); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/isExportsOrModuleAssignment-test.ts b/packages/react-docgen/src/utils/__tests__/isExportsOrModuleAssignment-test.ts deleted file mode 100644 index 8547f58b5d6..00000000000 --- a/packages/react-docgen/src/utils/__tests__/isExportsOrModuleAssignment-test.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { parse } from '../../../tests/utils'; -import isExportsOrModuleAssignment from '../isExportsOrModuleAssignment.js'; -import { describe, expect, test } from 'vitest'; - -describe('isExportsOrModuleAssignment', () => { - test('detects "module.exports = ...;"', () => { - expect( - isExportsOrModuleAssignment(parse.expression('module.exports = foo')), - ).toBe(true); - }); - - test('detects "exports.foo = ..."', () => { - expect( - isExportsOrModuleAssignment(parse.expression('exports.foo = foo')), - ).toBe(true); - }); - - test('does not accept "exports = foo;"', () => { - // That doesn't actually export anything - expect(isExportsOrModuleAssignment(parse.expression('exports = foo'))).toBe( - false, - ); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/isReactBuiltinReference-test.ts b/packages/react-docgen/src/utils/__tests__/isReactBuiltinReference-test.ts deleted file mode 100644 index 6a865a5de7d..00000000000 --- a/packages/react-docgen/src/utils/__tests__/isReactBuiltinReference-test.ts +++ /dev/null @@ -1,147 +0,0 @@ -import type { - Identifier, - MemberExpression, - QualifiedTypeIdentifier, - TSQualifiedName, - TSTypeAnnotation, - TypeAnnotation, - VariableDeclaration, -} from '@babel/types'; -import { parse, parseTypescript } from '../../../tests/utils'; -import isReactBuiltinReference from '../isReactBuiltinReference.js'; -import { describe, expect, test } from 'vitest'; -import type { NodePath } from '@babel/traverse'; - -describe('isReactBuiltinReference', () => { - describe('Commonjs require', () => { - test('returns true with a MemberExpression', () => { - const def = parse.expressionLast( - 'const React = require("react");React.foo', - ); - - expect(isReactBuiltinReference(def, 'foo')).toBe(true); - }); - - test('returns true with an Identifier', () => { - const def = parse.expressionLast( - 'const foo = require("react").foo;foo', - ); - - expect(isReactBuiltinReference(def, 'foo')).toBe(true); - }); - - test('returns true with an Identifier and a reassignment', () => { - const def = parse.expressionLast( - 'let foo; foo = require("react").foo;foo', - ); - - expect(isReactBuiltinReference(def, 'foo')).toBe(true); - }); - - test('returns true with an Identifier and destructuring', () => { - const def = parse.expressionLast( - 'const { foo } = require("react");foo', - ); - - expect(isReactBuiltinReference(def, 'foo')).toBe(true); - }); - }); - - describe('ESM import', () => { - test('returns true with a MemberExpression', () => { - const def = parse.expressionLast( - 'import React from "react";React.foo', - ); - - expect(isReactBuiltinReference(def, 'foo')).toBe(true); - }); - - test('returns true with a MemberExpression and namespace import', () => { - const def = parse.expressionLast( - 'import * as React from "react";React.foo', - ); - - expect(isReactBuiltinReference(def, 'foo')).toBe(true); - }); - - test('returns true with an Identifier', () => { - const def = parse.expressionLast( - 'import { foo } from "react";foo', - ); - - expect(isReactBuiltinReference(def, 'foo')).toBe(true); - }); - - test('returns true with an Identifier and StringIdentifier import', () => { - const def = parse.expressionLast( - 'import { "foo" as foo } from "react";foo', - ); - - expect(isReactBuiltinReference(def, 'foo')).toBe(true); - }); - - test('returns true with a Flow QualifiedTypeIdentifier', () => { - const def = ( - parse - .statementLast( - 'import React from "react";let x: React.foo', - ) - .get('declarations')[0] - .get('id') - .get('typeAnnotation') as NodePath - ) - .get('typeAnnotation') - .get('id') as NodePath; - - expect(isReactBuiltinReference(def, 'foo')).toBe(true); - }); - - test('returns true with a named import referenced in a flow type', () => { - const def = ( - parse - .statementLast( - 'import { foo } from "react";let x: foo', - ) - .get('declarations')[0] - .get('id') - .get('typeAnnotation') as NodePath - ) - .get('typeAnnotation') - .get('id') as NodePath; - - expect(isReactBuiltinReference(def, 'foo')).toBe(true); - }); - - test('returns true with a TS TSQualifiedName', () => { - const def = ( - parseTypescript - .statementLast( - 'import React from "react";let x: React.foo', - ) - .get('declarations')[0] - .get('id') - .get('typeAnnotation') as NodePath - ) - .get('typeAnnotation') - .get('typeName') as NodePath; - - expect(isReactBuiltinReference(def, 'foo')).toBe(true); - }); - - test('returns true with a named import referenced in a TS type', () => { - const def = ( - parseTypescript - .statementLast( - 'import { foo } from "react";let x: foo', - ) - .get('declarations')[0] - .get('id') - .get('typeAnnotation') as NodePath - ) - .get('typeAnnotation') - .get('typeName') as NodePath; - - expect(isReactBuiltinReference(def, 'foo')).toBe(true); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/isReactChildrenElementCall-test.ts b/packages/react-docgen/src/utils/__tests__/isReactChildrenElementCall-test.ts deleted file mode 100644 index c1b71074ca4..00000000000 --- a/packages/react-docgen/src/utils/__tests__/isReactChildrenElementCall-test.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { parse } from '../../../tests/utils'; -import isReactChildrenElementCall from '../isReactChildrenElementCall.js'; -import { describe, expect, test } from 'vitest'; - -describe('isReactChildrenElementCall', () => { - describe('true', () => { - test('React.Children.map', () => { - const def = parse.expressionLast(` - var React = require("React"); - React.Children.map(() => {}); - `); - - expect(isReactChildrenElementCall(def)).toBe(true); - }); - - test('React.Children.only', () => { - const def = parse.expressionLast(` - var React = require("React"); - React.Children.only(() => {}); - `); - - expect(isReactChildrenElementCall(def)).toBe(true); - }); - - test('React.Children.only without React', () => { - const def = parse.expressionLast(` - var Children = require("React").Children; - Children.only(() => {}); - `); - - expect(isReactChildrenElementCall(def)).toBe(true); - }); - - test('React.Children.only with destructuring', () => { - const def = parse.expressionLast(` - var { Children } = require("React"); - Children.only(() => {}); - `); - - expect(isReactChildrenElementCall(def)).toBe(true); - }); - - test('React.Children.only with import', () => { - const def = parse.expressionLast(` - import React from 'react'; - React.Children.only(() => {}); - `); - - expect(isReactChildrenElementCall(def)).toBe(true); - }); - - test('React.Children.only with named import', () => { - const def = parse.expressionLast(` - import { Children } from 'react'; - Children.only(() => {}); - `); - - expect(isReactChildrenElementCall(def)).toBe(true); - }); - }); - describe('false', () => { - test('not call expression', () => { - const def = parse.expressionLast(` - var React = require("React"); - React.Children.map; - `); - - expect(isReactChildrenElementCall(def)).toBe(false); - }); - - test('not MemberExpression', () => { - const def = parse.expressionLast(` - var React = require("React"); - map(); - `); - - expect(isReactChildrenElementCall(def)).toBe(false); - }); - - test('not only or map', () => { - const def = parse.expressionLast(` - var React = require("React"); - React.Children.abc(() => {}); - `); - - expect(isReactChildrenElementCall(def)).toBe(false); - }); - - test('not double MemberExpression', () => { - const def = parse.expressionLast(` - var React = require("React"); - Children.map(() => {}); - `); - - expect(isReactChildrenElementCall(def)).toBe(false); - }); - - test('not Children', () => { - const def = parse.expressionLast(` - var React = require("React"); - React.Parent.map(() => {}); - `); - - expect(isReactChildrenElementCall(def)).toBe(false); - }); - - test('not react module', () => { - const def = parse.expressionLast(` - var React = require("test"); - React.Children.map(() => {}); - `); - - expect(isReactChildrenElementCall(def)).toBe(false); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/isReactCloneElementCall-test.ts b/packages/react-docgen/src/utils/__tests__/isReactCloneElementCall-test.ts deleted file mode 100644 index eca78d2d1cc..00000000000 --- a/packages/react-docgen/src/utils/__tests__/isReactCloneElementCall-test.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { parse, makeMockImporter } from '../../../tests/utils'; -import isReactCloneElementCall from '../isReactCloneElementCall.js'; -import { describe, expect, test } from 'vitest'; - -describe('isReactCloneElementCall', () => { - const mockImporter = makeMockImporter({ - foo: (stmtLast) => - stmtLast(` - import React from 'react'; - export default React.cloneElement; - `).get('declaration'), - }); - - describe('built in React.createClass', () => { - test('accepts cloneElement called on React', () => { - const def = parse.expressionLast(` - var React = require("React"); - React.cloneElement({}); - `); - - expect(isReactCloneElementCall(def)).toBe(true); - }); - - test('accepts cloneElement called on aliased React', () => { - const def = parse.expressionLast(` - var other = require("React"); - other.cloneElement({}); - `); - - expect(isReactCloneElementCall(def)).toBe(true); - }); - - test('ignores other React calls', () => { - const def = parse.expressionLast(` - var React = require("React"); - React.isValidElement({}); - `); - - expect(isReactCloneElementCall(def)).toBe(false); - }); - - test('ignores non React calls to cloneElement', () => { - const def = parse.expressionLast(` - var React = require("bob"); - React.cloneElement({}); - `); - - expect(isReactCloneElementCall(def)).toBe(false); - }); - - test('accepts cloneElement called on destructed value', () => { - const def = parse.expressionLast(` - var { cloneElement } = require("react"); - cloneElement({}); - `); - - expect(isReactCloneElementCall(def)).toBe(true); - }); - - test('accepts cloneElement called on destructed aliased value', () => { - const def = parse.expressionLast(` - var { cloneElement: foo } = require("react"); - foo({}); - `); - - expect(isReactCloneElementCall(def)).toBe(true); - }); - - test('accepts cloneElement called on imported value', () => { - const def = parse.expressionLast(` - import { cloneElement } from "react"; - cloneElement({}); - `); - - expect(isReactCloneElementCall(def)).toBe(true); - }); - - test('accepts cloneElement called on imported aliased value', () => { - const def = parse.expressionLast(` - import { cloneElement as foo } from "react"; - foo({}); - `); - - expect(isReactCloneElementCall(def)).toBe(true); - }); - - test('can resolve cloneElement imported from an intermediate module', () => { - const def = parse.expressionLast( - ` - import foo from "foo"; - foo({}); - `, - mockImporter, - ); - - expect(isReactCloneElementCall(def)).toBe(true); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/isReactComponentClass-test.ts b/packages/react-docgen/src/utils/__tests__/isReactComponentClass-test.ts deleted file mode 100644 index 47d7c2b35af..00000000000 --- a/packages/react-docgen/src/utils/__tests__/isReactComponentClass-test.ts +++ /dev/null @@ -1,222 +0,0 @@ -import { parse, makeMockImporter } from '../../../tests/utils'; -import isReactComponentClass from '../isReactComponentClass.js'; -import { describe, expect, test } from 'vitest'; - -describe('isReactComponentClass', () => { - const mockImporter = makeMockImporter({ - component: (stmtLast) => - stmtLast(` - import React from 'react'; - export default React.Component; - `).get('declaration'), - - pureComponent: (stmtLast) => - stmtLast(` - import React from 'react'; - export default React.PureComponent; - `).get('declaration'), - }); - - describe('render method', () => { - test('ignores class declarations with a render method without superclass', () => { - const def = parse.statement('class Foo { render() {}}'); - - expect(isReactComponentClass(def)).toBe(false); - }); - - test('ignores class expression with a render method without superclass', () => { - const def = parse.expression('class { render() {}}'); - - expect(isReactComponentClass(def)).toBe(false); - }); - - test('ignores static render methods', () => { - const def = parse.statement('class Foo extends X { static render() {}}'); - - expect(isReactComponentClass(def)).toBe(false); - }); - - test('ignores dynamic render methods', () => { - const def = parse.statement( - 'class Foo extends X { static [render]() {}}', - ); - - expect(isReactComponentClass(def)).toBe(false); - }); - - test('ignores getter or setter render methods', () => { - let def = parse.statement('class Foo extends X { get render() {}}'); - - expect(isReactComponentClass(def)).toBe(false); - - def = parse.statement('class Foo extends X { set render(value) {}}'); - expect(isReactComponentClass(def)).toBe(false); - }); - }); - - describe('React.Component inheritance', () => { - test('accepts class declarations extending React.Component', () => { - const def = parse.statementLast(` - var React = require('react'); - class Foo extends React.Component {} - `); - - expect(isReactComponentClass(def)).toBe(true); - }); - - test('accepts class expressions extending React.Component', () => { - const def = parse - .statementLast( - ` - var React = require('react'); - var Foo = class extends React.Component {} - `, - ) - .get('declarations')[0] - .get('init'); - - expect(isReactComponentClass(def)).toBe(true); - }); - - test('resolves the super class reference', () => { - const def = parse.statementLast(` - var { Component } = require('react'); - var C = Component; - class Foo extends C {} - `); - - expect(isReactComponentClass(def)).toBe(true); - }); - - test('resolves the super class reference with named import', () => { - const def = parse.statementLast(` - import { Component } from 'react'; - class Foo extends Component {} - `); - - expect(isReactComponentClass(def)).toBe(true); - }); - - test('resolves the super class reference with default import', () => { - const def = parse.statementLast(` - import React from 'react'; - class Foo extends React.Component {} - `); - - expect(isReactComponentClass(def)).toBe(true); - }); - - test('resolves the super class reference with namespace import', () => { - const def = parse.statementLast(` - import * as React from 'react'; - class Foo extends React.Component {} - `); - - expect(isReactComponentClass(def)).toBe(true); - }); - - test('resolves the super class reference with alias', () => { - const def = parse.statementLast(` - var { Component: C } = require('react'); - class Foo extends C {} - `); - - expect(isReactComponentClass(def)).toBe(true); - }); - - test('does not accept references to other modules', () => { - const def = parse.statementLast( - ` - var { Component } = require('FakeReact'); - class Foo extends Component {} - `, - ); - - expect(isReactComponentClass(def)).toBe(false); - }); - - test('does not consider super class if render method is present', () => { - const def = parse.statementLast( - ` - var {Component} = require('FakeReact'); - class Foo extends Component { render() {} } - `, - ); - - expect(isReactComponentClass(def)).toBe(true); - }); - - test('can resolve Component from an intermediate module', () => { - const def = parse.statementLast( - `import RC from 'component'; - class Foo extends RC {}`, - mockImporter, - ); - - expect(isReactComponentClass(def)).toBe(true); - }); - }); - - describe('React.PureComponent inheritance', () => { - test('accepts class declarations extending React.PureComponent', () => { - const def = parse.statementLast( - `var React = require('react'); - class Foo extends React.PureComponent {}`, - ); - - expect(isReactComponentClass(def)).toBe(true); - }); - - test('accepts class expressions extending React.PureComponent', () => { - const def = parse - .statementLast( - `var React = require('react'); - var Foo = class extends React.PureComponent {}`, - ) - .get('declarations')[0] - .get('init'); - - expect(isReactComponentClass(def)).toBe(true); - }); - - test('resolves the super class reference', () => { - const def = parse.statementLast( - `var {PureComponent} = require('react'); - var C = PureComponent; - class Foo extends C {}`, - ); - - expect(isReactComponentClass(def)).toBe(true); - }); - - test('does not accept references to other modules', () => { - const def = parse.statementLast( - `var {PureComponent} = require('FakeReact'); - class Foo extends PureComponent {}`, - ); - - expect(isReactComponentClass(def)).toBe(false); - }); - - test('does not consider super class if render method is present', () => { - const def = parse.statementLast(` - var {PureComponent} = require('FakeReact'); - class Foo extends PureComponent { render() {} } - `); - - expect(isReactComponentClass(def)).toBe(true); - }); - - test('can resolve PureComponent from an intermediate module', () => { - const def = parse.statementLast( - ` - import PC from 'pureComponent'; - class Foo extends PC {} - `, - mockImporter, - ); - - expect(isReactComponentClass(def)).toBe(true); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/isReactComponentMethod-test.ts b/packages/react-docgen/src/utils/__tests__/isReactComponentMethod-test.ts deleted file mode 100644 index 236f42ee05d..00000000000 --- a/packages/react-docgen/src/utils/__tests__/isReactComponentMethod-test.ts +++ /dev/null @@ -1,74 +0,0 @@ -import type { ClassDeclaration, ObjectExpression } from '@babel/types'; -import { parse, makeMockImporter } from '../../../tests/utils'; -import isReactComponentMethod from '../isReactComponentMethod.js'; -import { describe, expect, test } from 'vitest'; - -describe('isReactComponentMethod', () => { - const mockImporter = makeMockImporter({ - foo: (stmtLast) => - stmtLast(` - export default 'render'; - `).get('declaration'), - }); - - test('returns true if the method is a component class method', () => { - const def = parse.statement('class Foo { render() {}}'); - const method = def.get('body').get('body')[0]; - - expect(isReactComponentMethod(method)).toBe(true); - }); - - test('returns true if the method is a component `createClass` object method', () => { - const def = parse.expression('{ render() {}}'); - const method = def.get('properties')[0]; - - expect(isReactComponentMethod(method)).toBe(true); - }); - - test('returns true if the method is a component `createClass` object property with arrow function', () => { - const def = parse.expression('{ render: () => {}}'); - const method = def.get('properties')[0]; - - expect(isReactComponentMethod(method)).toBe(true); - }); - - test('returns true if the method is a component `createClass` object property with function', () => { - const def = parse.expression('{ render: function () {}}'); - const method = def.get('properties')[0]; - - expect(isReactComponentMethod(method)).toBe(true); - }); - - test('returns false if the method is not a component class method', () => { - const def = parse.statement('class Foo { bar() {}}'); - const method = def.get('body').get('body')[0]; - - expect(isReactComponentMethod(method)).toBe(false); - }); - - test('returns false if the method is not a component `createClass` object method', () => { - const def = parse.expression('{ bar() {}}'); - const method = def.get('properties')[0]; - - expect(isReactComponentMethod(method)).toBe(false); - }); - - test('returns false if the path is not a method or object property', () => { - const def = parse.statement('let foo = "bar";'); - - expect(isReactComponentMethod(def)).toBe(false); - }); - - test('resolves imported value of computed property', () => { - const def = parse.statement( - ` - class Foo { [foo]() {}} - import foo from 'foo'; - `, - mockImporter, - ); - const method = def.get('body').get('body')[0]; - - expect(isReactComponentMethod(method)).toBe(true); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/isReactCreateClassCall-test.ts b/packages/react-docgen/src/utils/__tests__/isReactCreateClassCall-test.ts deleted file mode 100644 index 45abc98c45d..00000000000 --- a/packages/react-docgen/src/utils/__tests__/isReactCreateClassCall-test.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { parse, makeMockImporter } from '../../../tests/utils'; -import isReactCreateClassCall from '../isReactCreateClassCall.js'; -import { describe, expect, test } from 'vitest'; - -describe('isReactCreateClassCall', () => { - const mockImporter = makeMockImporter({ - foo: (stmtLast) => - stmtLast(` - import React from 'react'; - export default React.createClass; - `).get('declaration'), - - bar: (stmtLast) => - stmtLast(` - import makeClass from "create-react-class"; - export default makeClass; - `).get('declaration'), - }); - - describe('built in React.createClass', () => { - test('accepts createClass called on React', () => { - const def = parse.expressionLast(` - var React = require("React"); - React.createClass({ - render() {} - }); - `); - - expect(isReactCreateClassCall(def)).toBe(true); - }); - - test('accepts createClass called on aliased React', () => { - const def = parse.expressionLast(` - var other = require("React"); - other.createClass({ - render() {} - }); - `); - - expect(isReactCreateClassCall(def)).toBe(true); - }); - - test('ignores other React calls', () => { - const def = parse.expressionLast(` - var React = require("React"); - React.isValidElement({}); - `); - - expect(isReactCreateClassCall(def)).toBe(false); - }); - - test('ignores non React calls to createClass', () => { - const def = parse.expressionLast(` - var React = require("bob"); - React.createClass({ - render() {} - }); - `); - - expect(isReactCreateClassCall(def)).toBe(false); - }); - - test('accepts createClass called on destructed value', () => { - const def = parse.expressionLast(` - var { createClass } = require("react"); - createClass({}); - `); - - expect(isReactCreateClassCall(def)).toBe(true); - }); - - test('accepts createClass called on destructed aliased value', () => { - const def = parse.expressionLast(` - var { createClass: foo } = require("react"); - foo({}); - `); - - expect(isReactCreateClassCall(def)).toBe(true); - }); - - test('accepts createClass called on imported value', () => { - const def = parse.expressionLast(` - import { createClass } from "react"; - createClass({}); - `); - - expect(isReactCreateClassCall(def)).toBe(true); - }); - - test('accepts createClass called on imported aliased value', () => { - const def = parse.expressionLast(` - import { createClass as foo } from "react"; - foo({}); - `); - - expect(isReactCreateClassCall(def)).toBe(true); - }); - - test('resolves createClass imported from intermediate module', () => { - const def = parse.expressionLast( - ` - import foo from "foo"; - foo({}); - `, - mockImporter, - ); - - expect(isReactCreateClassCall(def)).toBe(true); - }); - }); - - describe('modular in create-react-class', () => { - test('accepts create-react-class', () => { - const def = parse.expressionLast(` - var createReactClass = require("create-react-class"); - createReactClass({ - render() {} - }); - `); - - expect(isReactCreateClassCall(def)).toBe(true); - }); - - test('accepts create-react-class calls on another name', () => { - const def = parse.expressionLast(` - var makeClass = require("create-react-class"); - makeClass({ - render() {} - }); - `); - - expect(isReactCreateClassCall(def)).toBe(true); - }); - - test('ignores non create-react-class calls to createReactClass', () => { - const def = parse.expressionLast(` - var createReactClass = require("bob"); - createReactClass({ - render() {} - }); - `); - - expect(isReactCreateClassCall(def)).toBe(false); - }); - - test('resolves create-react-class imported from intermediate module', () => { - const def = parse.expressionLast( - ` - import bar from "bar"; - bar({}); - `, - mockImporter, - ); - - expect(isReactCreateClassCall(def)).toBe(true); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/isReactCreateElementCall-test.ts b/packages/react-docgen/src/utils/__tests__/isReactCreateElementCall-test.ts deleted file mode 100644 index 61a7b37b8d4..00000000000 --- a/packages/react-docgen/src/utils/__tests__/isReactCreateElementCall-test.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { parse, makeMockImporter } from '../../../tests/utils'; -import isReactCreateElementCall from '../isReactCreateElementCall.js'; -import { describe, expect, test } from 'vitest'; - -describe('isReactCreateElementCall', () => { - const mockImporter = makeMockImporter({ - foo: (stmtLast) => - stmtLast(` - import React from 'react'; - export default React.createElement; - `).get('declaration'), - }); - - describe('built in React.createElement', () => { - test('accepts createElement called on React', () => { - const def = parse.expressionLast(` - var React = require("React"); - React.createElement({ - render() {} - }); - `); - - expect(isReactCreateElementCall(def)).toBe(true); - }); - - test('accepts createElement called on aliased React', () => { - const def = parse.expressionLast(` - var other = require("React"); - other.createElement({ - render() {} - }); - `); - - expect(isReactCreateElementCall(def)).toBe(true); - }); - - test('ignores other React calls', () => { - const def = parse.expressionLast(` - var React = require("React"); - React.isValidElement({}); - `); - - expect(isReactCreateElementCall(def)).toBe(false); - }); - - test('ignores non React calls to createElement', () => { - const def = parse.expressionLast(` - var React = require("bob"); - React.createElement({ - render() {} - }); - `); - - expect(isReactCreateElementCall(def)).toBe(false); - }); - - test('accepts createElement called on destructed value', () => { - const def = parse.expressionLast(` - var { createElement } = require("react"); - createElement({}); - `); - - expect(isReactCreateElementCall(def)).toBe(true); - }); - - test('accepts createElement called on destructed aliased value', () => { - const def = parse.expressionLast(` - var { createElement: foo } = require("react"); - foo({}); - `); - - expect(isReactCreateElementCall(def)).toBe(true); - }); - - test('accepts createElement called on imported value', () => { - const def = parse.expressionLast(` - import { createElement } from "react"; - createElement({}); - `); - - expect(isReactCreateElementCall(def)).toBe(true); - }); - - test('accepts createElement called on imported aliased value', () => { - const def = parse.expressionLast(` - import { createElement as foo } from "react"; - foo({}); - `); - - expect(isReactCreateElementCall(def)).toBe(true); - }); - - test('can resolve createElement imported from an intermediate module', () => { - const def = parse.expressionLast( - `import foo from "foo"; - foo({});`, - mockImporter, - ); - - expect(isReactCreateElementCall(def)).toBe(true); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/isReactForwardRefCall-test.ts b/packages/react-docgen/src/utils/__tests__/isReactForwardRefCall-test.ts deleted file mode 100644 index ff9965fca22..00000000000 --- a/packages/react-docgen/src/utils/__tests__/isReactForwardRefCall-test.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { makeMockImporter, parse } from '../../../tests/utils'; -import isReactForwardRefCall from '../isReactForwardRefCall.js'; -import { describe, expect, test } from 'vitest'; - -describe('isReactForwardRefCall', () => { - const mockImporter = makeMockImporter({ - foo: (stmtLast) => - stmtLast(` - import React from 'react'; - export default React.forwardRef; - `).get('declaration'), - }); - - describe('built in React.forwardRef', () => { - test('accepts forwardRef called on React', () => { - const def = parse.expressionLast(` - var React = require("React"); - React.forwardRef({ - render() {} - }); - `); - - expect(isReactForwardRefCall(def)).toBe(true); - }); - - test('accepts forwardRef called on aliased React', () => { - const def = parse.expressionLast(` - var other = require("React"); - other.forwardRef({ - render() {} - }); - `); - - expect(isReactForwardRefCall(def)).toBe(true); - }); - - test('ignores other React calls', () => { - const def = parse.expressionLast(` - var React = require("React"); - React.isValidElement({}); - `); - - expect(isReactForwardRefCall(def)).toBe(false); - }); - - test('ignores non React calls to forwardRef', () => { - const def = parse.expressionLast(` - var React = require("bob"); - React.forwardRef({ - render() {} - }); - `); - - expect(isReactForwardRefCall(def)).toBe(false); - }); - - test('accepts forwardRef called on destructed value', () => { - const def = parse.expressionLast(` - var { forwardRef } = require("react"); - forwardRef({}); - `); - - expect(isReactForwardRefCall(def)).toBe(true); - }); - - test('accepts forwardRef called on destructed aliased value', () => { - const def = parse.expressionLast(` - var { forwardRef: foo } = require("react"); - foo({}); - `); - - expect(isReactForwardRefCall(def)).toBe(true); - }); - - test('accepts forwardRef called on imported value', () => { - const def = parse.expressionLast(` - import { forwardRef } from "react"; - forwardRef({}); - `); - - expect(isReactForwardRefCall(def)).toBe(true); - }); - - test('does not accept forwardRef if not outer call', () => { - const def = parse.expressionLast(` - import { forwardRef, memo } from "react"; - memo(forwardRef({})); - `); - - expect(isReactForwardRefCall(def)).toBe(false); - }); - - test('accepts forwardRef called on imported aliased value', () => { - const def = parse.expressionLast(` - import { forwardRef as foo } from "react"; - foo({}); - `); - - expect(isReactForwardRefCall(def)).toBe(true); - }); - - test('can resolve forwardRef imported from an intermediate module', () => { - const def = parse.expressionLast( - ` - import foo from "foo"; - foo({}); - `, - mockImporter, - ); - - expect(isReactForwardRefCall(def)).toBe(true); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/isReactModuleName-test.ts b/packages/react-docgen/src/utils/__tests__/isReactModuleName-test.ts deleted file mode 100644 index 69a40889008..00000000000 --- a/packages/react-docgen/src/utils/__tests__/isReactModuleName-test.ts +++ /dev/null @@ -1,22 +0,0 @@ -import isReactModuleName from '../isReactModuleName.js'; -import { describe, expect, test } from 'vitest'; - -describe('isReactModuleName', () => { - const reactModules = [ - 'react', - 'react/addons', - 'react-native', - 'proptypes', - 'prop-types', - ]; - - reactModules.forEach((module) => { - test(`returns true for ${module}`, () => { - expect(isReactModuleName(module)).toBe(true); - }); - }); - - test(`returns false by default`, () => { - expect(isReactModuleName('not-react')).toBe(false); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/isRequiredPropType-test.ts b/packages/react-docgen/src/utils/__tests__/isRequiredPropType-test.ts deleted file mode 100644 index 8f7d4266d1b..00000000000 --- a/packages/react-docgen/src/utils/__tests__/isRequiredPropType-test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { parse } from '../../../tests/utils'; -import isRequiredPropType from '../isRequiredPropType.js'; -import { describe, expect, test } from 'vitest'; - -describe('isRequiredPropType', () => { - test('considers isRequired', () => { - expect(isRequiredPropType(parse.expression('foo.bar.isRequired'))).toEqual( - true, - ); - expect(isRequiredPropType(parse.expression('foo.isRequired.bar'))).toEqual( - true, - ); - }); - - test('considers ["isRequired"]', () => { - expect( - isRequiredPropType(parse.expression('foo.bar["isRequired"]')), - ).toEqual(true); - expect( - isRequiredPropType(parse.expression('foo["isRequired"].bar')), - ).toEqual(true); - }); - - test('ignores variables', () => { - expect(isRequiredPropType(parse.expression('foo.bar[isRequired]'))).toEqual( - false, - ); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/isStatelessComponent-test.ts b/packages/react-docgen/src/utils/__tests__/isStatelessComponent-test.ts deleted file mode 100644 index b40e8e20346..00000000000 --- a/packages/react-docgen/src/utils/__tests__/isStatelessComponent-test.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { parse } from '../../../tests/utils'; -import isStatelessComponent from '../isStatelessComponent.js'; -import { describe, expect, test } from 'vitest'; - -describe('isStatelessComponent', () => { - test('accepts jsx', () => { - const def = parse(` - var React = require('react'); - var Foo = () =>
; - `) - .get('body')[1] - .get('declarations')[0] - .get('init'); - - expect(isStatelessComponent(def)).toBe(true); - }); - - test('accepts jsx fragment', () => { - const def = parse(` - var React = require('react'); - var Foo = () => <>; - `) - .get('body')[1] - .get('declarations')[0] - .get('init'); - - expect(isStatelessComponent(def)).toBe(true); - }); - - test('accepts createElement', () => { - const def = parse(` - var React = require('react'); - var Foo = () => React.createElement("div", null); - `) - .get('body')[1] - .get('declarations')[0] - .get('init'); - - expect(isStatelessComponent(def)).toBe(true); - }); - - test('accepts cloneElement', () => { - const def = parse(` - var React = require('react'); - var Foo = () => React.cloneElement("div", null); - `) - .get('body')[1] - .get('declarations')[0] - .get('init'); - - expect(isStatelessComponent(def)).toBe(true); - }); - - test('accepts React.Children.only', () => { - const def = parse(` - var React = require('react'); - var Foo = () => React.Children.only(children); - `) - .get('body')[1] - .get('declarations')[0] - .get('init'); - - expect(isStatelessComponent(def)).toBe(true); - }); - - test('accepts React.Children.map', () => { - const def = parse(` - var React = require('react'); - var Foo = () => React.Children.map(children, child => child); - `) - .get('body')[1] - .get('declarations')[0] - .get('init'); - - expect(isStatelessComponent(def)).toBe(true); - }); - - test('accepts different name than React', () => { - const def = parse(` - var AlphaBetters = require('react'); - var Foo = () => AlphaBetters.createElement("div", null); - `) - .get('body')[1] - .get('declarations')[0] - .get('init'); - - expect(isStatelessComponent(def)).toBe(true); - }); - - test('Stateless Function Components inside module pattern', () => { - const def = parse(` - var React = require('react'); - var Foo = { - Bar() { return
; }, - Baz: function() { return React.createElement('div'); }, - ['hello']: function() { return React.createElement('div'); }, - render() { return 7; }, - world: function({ children }) { return React.cloneElement(children, {}); }, - } - `) - .get('body')[1] - .get('declarations')[0] - .get('init'); - - const bar = def.get('properties')[0]; - const baz = def.get('properties')[1].get('value'); - const hello = def.get('properties')[2].get('value'); - const render = def.get('properties')[3]; - const world = def.get('properties')[4].get('value'); - - expect(isStatelessComponent(bar)).toBe(true); - expect(isStatelessComponent(baz)).toBe(true); - expect(isStatelessComponent(hello)).toBe(true); - expect(isStatelessComponent(render)).toBe(false); - expect(isStatelessComponent(world)).toBe(true); - }); - - describe('is not overzealous', () => { - test('does not accept declarations with a render method', () => { - const def = parse.statement(` - class Foo { - render() { - return
; - } - } - `); - - expect(isStatelessComponent(def)).toBe(false); - }); - - test('does not accept React.Component classes', () => { - const def = parse(` - var React = require('react'); - class Foo extends React.Component { - render() { - return
; - } - } - `).get('body')[1]; - - expect(isStatelessComponent(def)).toBe(false); - }); - - test('does not accept React.createClass calls', () => { - const def = parse.statement(` - React.createClass({ - render() { - return
; - } - }); - `); - - expect(isStatelessComponent(def)).toBe(false); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/isUnreachableFlowType-test.ts b/packages/react-docgen/src/utils/__tests__/isUnreachableFlowType-test.ts deleted file mode 100644 index e42fff848d3..00000000000 --- a/packages/react-docgen/src/utils/__tests__/isUnreachableFlowType-test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { ImportDeclaration } from '@babel/types'; -import { parse } from '../../../tests/utils'; -import isUnreachableFlowType from '../isUnreachableFlowType.js'; -import { describe, expect, test } from 'vitest'; - -describe('isUnreachableFlowType', () => { - test('considers Identifier as unreachable', () => { - expect(isUnreachableFlowType(parse.expression('foo'))).toBe(true); - }); - - test('considers any ImportSpecifier as unreachable', () => { - expect( - isUnreachableFlowType( - parse - .statement('import x from "";') - .get('specifiers')[0], - ), - ).toBe(true); - }); - - test('considers CallExpression as unreachable', () => { - expect(isUnreachableFlowType(parse.expression('foo()'))).toBe(true); - }); - - test('considers VariableDeclaration not as unreachable', () => { - expect(isUnreachableFlowType(parse.statement('const x = 1;'))).toBe(false); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/normalizeClassDefinition-test.ts b/packages/react-docgen/src/utils/__tests__/normalizeClassDefinition-test.ts deleted file mode 100644 index b1d12c10a1b..00000000000 --- a/packages/react-docgen/src/utils/__tests__/normalizeClassDefinition-test.ts +++ /dev/null @@ -1,128 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { - AssignmentExpression, - ClassDeclaration, - ClassExpression, - ClassProperty, - ExportDefaultDeclaration, - ExpressionStatement, - Identifier, - NumericLiteral, - VariableDeclaration, -} from '@babel/types'; -import { parse } from '../../../tests/utils'; -import normalizeClassDefinition from '../normalizeClassDefinition.js'; -import { describe, expect, test } from 'vitest'; - -describe('normalizeClassDefinition', () => { - test('finds assignments to class declarations', () => { - const classDefinition = parse.statement(` - class Foo {} - Foo.propTypes = 42; - `); - - normalizeClassDefinition(classDefinition); - const classProperty = classDefinition.node.body.body[0] as ClassProperty; - - expect(classProperty).toBeDefined(); - expect((classProperty.key as Identifier).name).toBe('propTypes'); - expect((classProperty.value as NumericLiteral).value).toBe(42); - expect(classProperty.static).toBe(true); - }); - - test('should not fail on classes without ids', () => { - const classDefinition = parse - .statement( - ` - export default class extends React.Component { - static propTypes = 42; - } - `, - ) - .get('declaration') as NodePath; - - normalizeClassDefinition(classDefinition); - const classProperty = classDefinition.node.body.body[0] as ClassProperty; - - expect(classProperty).toBeDefined(); - }); - - test('finds assignments to class expressions with variable declaration', () => { - const classDefinition = parse - .statement( - ` - var Foo = class {}; - Foo.propTypes = 42; - `, - ) - .get('declarations')[0] - .get('init') as NodePath; - - normalizeClassDefinition(classDefinition); - const classProperty = classDefinition.node.body.body[0] as ClassProperty; - - expect(classProperty).toBeDefined(); - expect((classProperty.key as Identifier).name).toBe('propTypes'); - expect((classProperty.value as NumericLiteral).value).toBe(42); - expect(classProperty.static).toBe(true); - }); - - test('finds assignments to class expressions with assignment', () => { - const classDefinition = ( - parse - .statement( - `var Foo; - Foo = class {}; - Foo.propTypes = 42;`, - 1, - ) - .get('expression') as NodePath - ).get('right') as NodePath; - - normalizeClassDefinition(classDefinition); - const classProperty = classDefinition.node.body.body[0] as ClassProperty; - - expect(classProperty).toBeDefined(); - expect((classProperty.key as Identifier).name).toBe('propTypes'); - expect((classProperty.value as NumericLiteral).value).toBe(42); - expect(classProperty.static).toBe(true); - }); - - test('ignores assignments further up the tree', () => { - const classDefinition = parse - .statement( - ` - var Foo = function() { - (class {}); - }; - Foo.bar = 42; - `, - ) - .get('declarations')[0] - .get('init') - .get('body') - .get('body')[0] - .get('expression'); - - normalizeClassDefinition(classDefinition); - const classProperty = classDefinition.node.body.body[0] as ClassProperty; - - expect(classProperty).not.toBeDefined(); - }); - - test('copies comments to class property', () => { - const classDefinition = parse.statement(` - class Foo {} - - // my comment - Foo.propTypes = 42; - `); - - normalizeClassDefinition(classDefinition); - const classProperty = classDefinition.node.body.body[0] as ClassProperty; - - expect(classProperty).toBeDefined(); - expect(classProperty.leadingComments?.length).toBe(1); - expect(classProperty.leadingComments?.[0].value).toBe(' my comment'); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/parseJsDoc-test.ts b/packages/react-docgen/src/utils/__tests__/parseJsDoc-test.ts deleted file mode 100644 index 045a9b37339..00000000000 --- a/packages/react-docgen/src/utils/__tests__/parseJsDoc-test.ts +++ /dev/null @@ -1,48 +0,0 @@ -import parseJsDoc from '../parseJsDoc.js'; -import { describe, expect, test } from 'vitest'; - -describe('parseJsDoc', () => { - describe('description', () => { - test('extracts the method description in jsdoc', () => { - const docblock = ` - Don't use this! - `; - - expect(parseJsDoc(docblock)).toMatchSnapshot(); - }); - }); - describe('@param', () => { - const docBlocks = { - 'extracts jsdoc description': '@param bar test', - 'extracts jsdoc empty description': '@param {string} bar', - 'extracts jsdoc union type param': '@param {string|Object|some[]} bar', - 'extracts jsdoc optional': '@param {string=} bar', - 'extracts jsdoc typed array': '@param {[string, number]} bar', - }; - - Object.keys(docBlocks).forEach((name) => { - const docBlock = docBlocks[name]; - - test(name, () => { - expect(parseJsDoc(docBlock)).toMatchSnapshot(); - }); - }); - }); - describe('@returns', () => { - const docBlocks = { - 'extracts jsdoc types': '@returns {string}', - 'extracts jsdoc mixed types': '@returns {*}', - 'extracts description from jsdoc': '@returns The number', - 'works with @return': '@return The number', - 'extracts jsdoc typed array': '@param {[string, number]} bar', - }; - - Object.keys(docBlocks).forEach((name) => { - const docBlock = docBlocks[name]; - - test(name, () => { - expect(parseJsDoc(docBlock)).toMatchSnapshot(); - }); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/printValue-test.ts b/packages/react-docgen/src/utils/__tests__/printValue-test.ts deleted file mode 100644 index 4d9b3c1ce76..00000000000 --- a/packages/react-docgen/src/utils/__tests__/printValue-test.ts +++ /dev/null @@ -1,75 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { ExpressionStatement, TSInterfaceDeclaration } from '@babel/types'; -import { parse, parseTypescript } from '../../../tests/utils'; -import printValue from '../printValue.js'; -import { describe, expect, test } from 'vitest'; - -describe('printValue', () => { - function pathFromSource(source: string): NodePath { - return parse.statement(source).get('expression'); - } - - test('does not print leading comments', () => { - expect(printValue(pathFromSource('//foo\nbar'))).toEqual('bar'); - }); - - test('does not print trailing comments', () => { - expect(printValue(pathFromSource('bar//foo'))).toEqual('bar'); - }); - - test('deindents code', () => { - expect( - printValue( - pathFromSource(` ( function () { - return x; - })`), - ), - ).toMatchSnapshot(); - }); - - [',', ';'].forEach((char) => { - test(`removes trailing ${char} for TsConstructSignatureDeclaration`, () => { - const path = parseTypescript - .statement( - `interface A { new (x:number)${char} }`, - ) - .get('body.body.0') as NodePath; - - expect(printValue(path)).toMatchSnapshot(); - }); - - test(`removes trailing ${char} for TsIndexSignature`, () => { - const path = parseTypescript - .statement( - `interface A { [x:string]: number${char} }`, - ) - .get('body.body.0') as NodePath; - - expect(printValue(path)).toMatchSnapshot(); - }); - - test(`removes trailing ${char} for TsCallSignatureDeclaration`, () => { - const path = parseTypescript - .statement(`interface A { (): number${char} }`) - .get('body.body.0') as NodePath; - - expect(printValue(path)).toMatchSnapshot(); - }); - - test(`removes trailing ${char} for TsPropertySignature`, () => { - const path = parseTypescript - .statement(`interface A { x: number${char} }`) - .get('body.body.0') as NodePath; - - expect(printValue(path)).toMatchSnapshot(); - }); - - test(`removes trailing ${char} for TsMethodSignature`, () => { - const path = parseTypescript - .statement(`interface A { x(): number${char} }`) - .get('body.body.0') as NodePath; - - expect(printValue(path)).toMatchSnapshot(); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/resolveExportDeclaration-test.ts b/packages/react-docgen/src/utils/__tests__/resolveExportDeclaration-test.ts deleted file mode 100644 index 4cb3a7bd212..00000000000 --- a/packages/react-docgen/src/utils/__tests__/resolveExportDeclaration-test.ts +++ /dev/null @@ -1,85 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { - ExportDefaultDeclaration, - ExportNamedDeclaration, -} from '@babel/types'; -import { parse } from '../../../tests/utils'; -import resolveExportDeclaration from '../resolveExportDeclaration.js'; -import { describe, expect, test, vi } from 'vitest'; - -vi.mock('../resolveToValue.js', () => ({ default: (path: NodePath) => path })); - -describe('resolveExportDeclaration', () => { - test('resolves default exports', () => { - const exp = parse.statement('export default 42;'); - const resolved = resolveExportDeclaration(exp); - - expect(resolved).toEqual([exp.get('declaration')]); - }); - - test('resolves named variable exports', () => { - const exp = parse.statement( - 'export var foo = 42, bar = 21;', - ); - const resolved = resolveExportDeclaration(exp); - - const declarations = exp.get('declaration').get('declarations'); - - expect(resolved).toEqual([declarations[0], declarations[1]]); - }); - - test('resolves named function exports', () => { - const exp = parse.statement( - 'export function foo(){}', - ); - const resolved = resolveExportDeclaration(exp); - - expect(resolved).toEqual([exp.get('declaration')]); - }); - - test('resolves named class exports', () => { - const exp = parse.statement('export class Foo {}'); - const resolved = resolveExportDeclaration(exp); - - expect(resolved).toEqual([exp.get('declaration')]); - }); - - test('resolves named exports', () => { - const exp = parse.statement( - 'export {foo, bar, baz}; var foo, bar, baz;', - ); - const resolved = resolveExportDeclaration(exp); - - const specifiers = exp.get('specifiers'); - - expect(resolved).toEqual([ - specifiers[0].get('local'), - specifiers[1].get('local'), - specifiers[2].get('local'), - ]); - }); - - test('resolves named exports from', () => { - const exp = parse.statement( - 'export {foo, bar, baz} from "";', - ); - const resolved = resolveExportDeclaration(exp); - - const specifiers = exp.get('specifiers'); - - expect(resolved).toEqual([ - specifiers[0].get('local'), - specifiers[1].get('local'), - specifiers[2].get('local'), - ]); - }); - - test('resolves named exports from with namespace', () => { - const exp = parse.statement( - 'export * as foo from "";', - ); - const resolved = resolveExportDeclaration(exp); - - expect(resolved).toEqual([]); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/resolveFunctionDefinitionToReturnValue-test.ts b/packages/react-docgen/src/utils/__tests__/resolveFunctionDefinitionToReturnValue-test.ts deleted file mode 100644 index 42731c79fa6..00000000000 --- a/packages/react-docgen/src/utils/__tests__/resolveFunctionDefinitionToReturnValue-test.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { FunctionDeclaration } from '@babel/types'; -import { parse } from '../../../tests/utils'; -import resolveFunctionDefinitionToReturnValue from '../resolveFunctionDefinitionToReturnValue.js'; -import { describe, expect, test } from 'vitest'; - -describe('resolveFunctionDefinitionToReturnValue', () => { - test('can resolve easy return statement', () => { - const path = parse.statement(` - function x () { return "result"; } - `); - - expect(resolveFunctionDefinitionToReturnValue(path)).toMatchSnapshot(); - }); - - test('stops after first return', () => { - const path = parse.statement(` - function x () { return "first"; return "second"; } - `); - - expect(resolveFunctionDefinitionToReturnValue(path)).toMatchSnapshot(); - }); - - test('ignores return values in other blocks', () => { - const path = parse.statement(` - function x () { - const a = function () { return "funcexpr"; } - const b = () => { return "arrow"; } - function c () { return "funcdecl"; } - const d = { - d() { return "objmthd"; } - } - - class A { - method() { - return "classmthd"; - } - } - - if (e) { - return "if"; - } else { - return "else"; - } - } - `); - - expect(resolveFunctionDefinitionToReturnValue(path)).toBeNull(); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/resolveGenericTypeAnnotations-test.ts b/packages/react-docgen/src/utils/__tests__/resolveGenericTypeAnnotations-test.ts deleted file mode 100644 index 4c6c45e8ebd..00000000000 --- a/packages/react-docgen/src/utils/__tests__/resolveGenericTypeAnnotations-test.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { parse } from '../../../tests/utils'; -import resolveGenericTypeAnnotation from '../resolveGenericTypeAnnotation.js'; -import { describe, expect, test } from 'vitest'; - -describe('resolveGenericTypeAnnotation', () => { - test('resolves type', () => { - const code = ` - var x: Props; - type Props = { x: string }; - `; - - expect( - resolveGenericTypeAnnotation( - parse - .statement(code) - .get('declarations')[0] - .get('id') - .get('typeAnnotation') - .get('typeAnnotation'), - ), - ).toMatchSnapshot(); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/resolveHOC-test.ts b/packages/react-docgen/src/utils/__tests__/resolveHOC-test.ts deleted file mode 100644 index b6565c55507..00000000000 --- a/packages/react-docgen/src/utils/__tests__/resolveHOC-test.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { makeMockImporter, parse } from '../../../tests/utils'; -import resolveHOC from '../resolveHOC.js'; -import { describe, expect, test } from 'vitest'; - -describe('resolveHOC', () => { - const mockImporter = makeMockImporter({ - component: (stmtLast) => - stmtLast(` - export default Component; - `).get('declaration'), - - hoc: (stmtLast) => - stmtLast(` - import foo from 'component'; - export default hoc1(foo); - `).get('declaration'), - }); - - test('resolves simple hoc', () => { - const path = parse.expressionLast(['hoc(Component);'].join('\n')); - - expect(resolveHOC(path)).toMatchSnapshot(); - }); - - test('resolves simple hoc w/ multiple args', () => { - const path = parse.expressionLast( - ['hoc1(arg1a, arg1b)(Component);'].join('\n'), - ); - - expect(resolveHOC(path)).toMatchSnapshot(); - }); - - test('resolves nested hocs', () => { - const path = parse.expressionLast( - `hoc2(arg2b, arg2b)( - hoc1(arg1a, arg2a)(Component) - );`, - ); - - expect(resolveHOC(path)).toMatchSnapshot(); - }); - - test('resolves really nested hocs', () => { - const path = parse.expressionLast( - `hoc3(arg3a, arg3b)( - hoc2(arg2b, arg2b)( - hoc1(arg1a, arg2a)(Component) - ) - );`, - ); - - expect(resolveHOC(path)).toMatchSnapshot(); - }); - - test('resolves HOC with additional params', () => { - const path = parse.expressionLast(`hoc3(Component, {})`); - - expect(resolveHOC(path)).toMatchSnapshot(); - }); - - test('resolves HOC as last element if first is literal', () => { - const path = parse.expressionLast(`hoc3(41, Component)`); - - expect(resolveHOC(path)).toMatchSnapshot(); - }); - - test('resolves HOC as last element if first is array', () => { - const path = parse.expressionLast(`hoc3([], Component)`); - - expect(resolveHOC(path)).toMatchSnapshot(); - }); - - test('resolves HOC as last element if first is object', () => { - const path = parse.expressionLast(`hoc3({}, Component)`); - - expect(resolveHOC(path)).toMatchSnapshot(); - }); - - test('resolves HOC as last element if first is spread', () => { - const path = parse.expressionLast(`hoc3(...params, Component)`); - - expect(resolveHOC(path)).toMatchSnapshot(); - }); - - test('resolves intermediate hocs', () => { - const path = parse.expressionLast( - ['const Component = React.memo(42);', 'hoc()(Component);'].join('\n'), - ); - - expect(resolveHOC(path)).toMatchSnapshot(); - }); - - test('can resolve an imported component passed to hoc', () => { - const path = parse.expressionLast( - ` - import foo from 'component'; - hoc(foo); - `, - mockImporter, - ); - - expect(resolveHOC(path)).toMatchSnapshot(); - }); - - test('can resolve an imported component passed to nested hoc', () => { - const path = parse.expressionLast( - ` - import foo from 'component'; - hoc2(arg2b, arg2b)( - hoc1(arg1a, arg2a)(foo) - ); - `, - mockImporter, - ); - - expect(resolveHOC(path)).toMatchSnapshot(); - }); - - test('can resolve an hocs inside imported component passed to hoc', () => { - const path = parse.expressionLast( - `import bar from 'hoc'; - hoc(bar);`, - mockImporter, - ); - - expect(resolveHOC(path)).toMatchSnapshot(); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/resolveObjectKeysToArray-test.ts b/packages/react-docgen/src/utils/__tests__/resolveObjectKeysToArray-test.ts deleted file mode 100644 index ee06409a02f..00000000000 --- a/packages/react-docgen/src/utils/__tests__/resolveObjectKeysToArray-test.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { makeMockImporter, parse } from '../../../tests/utils'; -import resolveObjectKeysToArray from '../resolveObjectKeysToArray.js'; -import { describe, expect, test } from 'vitest'; - -describe('resolveObjectKeysToArray', () => { - const mockImporter = makeMockImporter({ - foo: (stmtLast) => - stmtLast(` - export default { - bar: "bar", - "foo": "foo", - 1: 0, - 2: 5, - [3]: 3, - ['baz']: "baz", - }; - `).get('declaration'), - - bar: (stmtLast) => - stmtLast(` - export default { - bar: 'bar', - }; - `).get('declaration'), - }); - - test('resolves Object.keys with identifiers', () => { - const path = parse.expressionLast( - ['var foo = { bar: 1, foo: 2 };', 'Object.keys(foo);'].join('\n'), - ); - - expect(resolveObjectKeysToArray(path)).toMatchSnapshot(); - }); - - test('resolves Object.keys with literals', () => { - const path = parse.expressionLast( - ['var foo = { "bar": 1, 5: 2 };', 'Object.keys(foo);'].join('\n'), - ); - - expect(resolveObjectKeysToArray(path)).toMatchSnapshot(); - }); - - test('resolves Object.keys with literals as computed key', () => { - const path = parse.expressionLast( - ['var foo = { ["bar"]: 1, [5]: 2};', 'Object.keys(foo);'].join('\n'), - ); - - expect(resolveObjectKeysToArray(path)).toMatchSnapshot(); - }); - - test('resolves Object.keys when using resolvable spread', () => { - const path = parse.expressionLast( - [ - 'var bar = { doo: 4 }', - 'var foo = { boo: 1, foo: 2, ...bar };', - 'Object.keys(foo);', - ].join('\n'), - ); - - expect(resolveObjectKeysToArray(path)).toMatchSnapshot(); - }); - - test('resolves Object.keys when using getters', () => { - const path = parse.expressionLast( - ['var foo = { boo: 1, foo: 2, get bar() {} };', 'Object.keys(foo);'].join( - '\n', - ), - ); - - expect(resolveObjectKeysToArray(path)).toMatchSnapshot(); - }); - - test('resolves Object.keys when using setters', () => { - const path = parse.expressionLast( - [ - 'var foo = { boo: 1, foo: 2, set bar(e) {} };', - 'Object.keys(foo);', - ].join('\n'), - ); - - expect(resolveObjectKeysToArray(path)).toMatchSnapshot(); - }); - - test('resolves Object.keys but ignores duplicates', () => { - const path = parse.expressionLast( - [ - 'var bar = { doo: 4, doo: 5 }', - 'var foo = { boo: 1, foo: 2, doo: 1, ...bar };', - 'Object.keys(foo);', - ].join('\n'), - ); - - expect(resolveObjectKeysToArray(path)).toMatchSnapshot(); - }); - - test('resolves Object.keys but ignores duplicates with getter and setter', () => { - const path = parse.expressionLast( - ['var foo = { get x() {}, set x(a) {} };', 'Object.keys(foo);'].join( - '\n', - ), - ); - - expect(resolveObjectKeysToArray(path)).toMatchSnapshot(); - }); - - test('does not resolve Object.keys when using unresolvable spread', () => { - const path = parse.expressionLast( - ['var foo = { bar: 1, foo: 2, ...bar };', 'Object.keys(foo);'].join('\n'), - ); - - expect(resolveObjectKeysToArray(path)).toBeNull(); - }); - - test('does not resolve Object.keys when using computed keys', () => { - const path = parse.expressionLast( - ['var foo = { [bar]: 1, foo: 2 };', 'Object.keys(foo);'].join('\n'), - ); - - expect(resolveObjectKeysToArray(path)).toBeNull(); - }); - - test('can resolve imported objects passed to Object.keys', () => { - const path = parse.expressionLast( - `import foo from 'foo'; - Object.keys(foo);`, - mockImporter, - ); - - expect(resolveObjectKeysToArray(path)).toMatchSnapshot(); - }); - - test('can resolve spreads from imported objects', () => { - const path = parse.expressionLast( - `import bar from 'bar'; - var abc = { foo: 'foo', baz: 'baz', ...bar }; - Object.keys(abc);`, - mockImporter, - ); - - expect(resolveObjectKeysToArray(path)).toMatchSnapshot(); - }); - - test('can handle unresolved imported objects passed to Object.values', () => { - const path = parse.expressionLast( - `import foo from 'foo'; - Object.keys(foo);`, - ); - - expect(resolveObjectKeysToArray(path)).toBe(null); - }); - - test('can handle unresolve spreads from imported objects', () => { - const path = parse.expressionLast( - `import bar from 'bar'; - var abc = { foo: 'foo', baz: 'baz', ...bar }; - Object.keys(abc);`, - ); - - expect(resolveObjectKeysToArray(path)).toBe(null); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/resolveObjectPatternPropertyToValue-test.ts b/packages/react-docgen/src/utils/__tests__/resolveObjectPatternPropertyToValue-test.ts deleted file mode 100644 index 4db175b66c9..00000000000 --- a/packages/react-docgen/src/utils/__tests__/resolveObjectPatternPropertyToValue-test.ts +++ /dev/null @@ -1,94 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { - AssignmentExpression, - ObjectExpression, - ObjectProperty, - VariableDeclaration, -} from '@babel/types'; -import { parse } from '../../../tests/utils'; -import resolveObjectPatternPropertyToValue from '../resolveObjectPatternPropertyToValue.js'; -import { describe, expect, test } from 'vitest'; - -describe('resolveObjectPatternPropertyToValue', () => { - test('does not resolve if not in ObjectProperty', () => { - const path = parse - .expressionLast( - `const x = { a : "string" }; - ({ a })`, - ) - .get('properties.0') as NodePath; - - expect(resolveObjectPatternPropertyToValue(path)).toBeNull(); - }); - - test('does not resolve if not in VariableDeclarator or AssignmentExpression', () => { - const path = parse - .expression(`({ a }) => {}`) - .get('params.0.properties.0') as NodePath; - - expect(resolveObjectPatternPropertyToValue(path)).toBeNull(); - }); - - describe('VariableDeclarator', () => { - test('resolved basic case', () => { - const path = parse - .statementLast( - `const x = { a : "string" }; - const { a } = x;`, - ) - .get('declarations.0.id.properties.0') as NodePath; - - expect(resolveObjectPatternPropertyToValue(path)).toMatchSnapshot(); - }); - - test('does not resolve if property not found', () => { - const path = parse - .statementLast( - `const x = { b : "string" }; - const { a } = x;`, - ) - .get('declarations.0.id.properties.0') as NodePath; - - expect(resolveObjectPatternPropertyToValue(path)).toBeNull(); - }); - - test('does not resolve when init not resolvable', () => { - const path = parse - .statementLast(`const { a } = x;`) - .get('declarations.0.id.properties.0') as NodePath; - - expect(resolveObjectPatternPropertyToValue(path)).toBeNull(); - }); - }); - describe('AssignmentExpression', () => { - test('resolved basic case', () => { - const path = parse - .expressionLast( - `const x = { a : "string" }; - ({ a } = x)`, - ) - .get('left.properties.0') as NodePath; - - expect(resolveObjectPatternPropertyToValue(path)).toMatchSnapshot(); - }); - - test('does not resolve if property not found', () => { - const path = parse - .expressionLast( - `const x = { b : "string" }; - ({ a } = x)`, - ) - .get('left.properties.0') as NodePath; - - expect(resolveObjectPatternPropertyToValue(path)).toBeNull(); - }); - - test('does not resolve when init not resolvable', () => { - const path = parse - .expression(`{ a } = x`) - .get('left.properties.0') as NodePath; - - expect(resolveObjectPatternPropertyToValue(path)).toBeNull(); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/resolveObjectValuesToArray-test.ts b/packages/react-docgen/src/utils/__tests__/resolveObjectValuesToArray-test.ts deleted file mode 100644 index 797c6507cb6..00000000000 --- a/packages/react-docgen/src/utils/__tests__/resolveObjectValuesToArray-test.ts +++ /dev/null @@ -1,196 +0,0 @@ -import { makeMockImporter, parse } from '../../../tests/utils'; -import resolveObjectValuesToArray from '../resolveObjectValuesToArray.js'; -import { describe, expect, test } from 'vitest'; - -describe('resolveObjectValuesToArray', () => { - const mockImporter = makeMockImporter({ - foo: (stmtLast) => - stmtLast(` - export default { - 1: "bar", - 2: "foo", - 3: 0, - 4: 5, - 5: undefined, - 6: null, - [7]: 7, - ['foo']: "foo", - }; - `).get('declaration'), - - bar: (stmtLast) => - stmtLast(` - export default { - bar: 'bar', - }; - `).get('declaration'), - }); - - test('resolves Object.values with strings', () => { - const path = parse.expressionLast( - ['var foo = { 1: "bar", 2: "foo" };', 'Object.values(foo);'].join('\n'), - ); - - expect(resolveObjectValuesToArray(path)).toMatchSnapshot(); - }); - - test('resolves Object.values with numbers', () => { - const path = parse.expressionLast( - ['var foo = { 1: 0, 2: 5 };', 'Object.values(foo);'].join('\n'), - ); - - expect(resolveObjectValuesToArray(path)).toMatchSnapshot(); - }); - - test('resolves Object.values with undefined or null', () => { - const path = parse.expressionLast( - ['var foo = { 1: null, 2: undefined };', 'Object.values(foo);'].join( - '\n', - ), - ); - - expect(resolveObjectValuesToArray(path)).toMatchSnapshot(); - }); - - test('resolves Object.values with literals as computed key', () => { - const path = parse.expressionLast( - ['var foo = { ["bar"]: 1, [5]: 2};', 'Object.values(foo);'].join('\n'), - ); - - expect(resolveObjectValuesToArray(path)).toMatchSnapshot(); - }); - - test('does not resolve Object.values with complex computed key', () => { - const path = parse.expressionLast( - ['var foo = { [()=>{}]: 1, [5]: 2};', 'Object.values(foo);'].join('\n'), - ); - - expect(resolveObjectValuesToArray(path)).toBeNull(); - }); - - test('resolves Object.values when using resolvable spread', () => { - const path = parse.expressionLast( - [ - 'var bar = { doo: 4 }', - 'var foo = { boo: 1, foo: 2, ...bar };', - 'Object.values(foo);', - ].join('\n'), - ); - - expect(resolveObjectValuesToArray(path)).toMatchSnapshot(); - }); - - test('resolves Object.values when using getters', () => { - const path = parse.expressionLast( - [ - 'var foo = { boo: 1, foo: 2, get bar() {} };', - 'Object.values(foo);', - ].join('\n'), - ); - - expect(resolveObjectValuesToArray(path)).toMatchSnapshot(); - }); - - test('resolves Object.values when using setters', () => { - const path = parse.expressionLast( - [ - 'var foo = { boo: 1, foo: 2, set bar(e) {} };', - 'Object.values(foo);', - ].join('\n'), - ); - - expect(resolveObjectValuesToArray(path)).toMatchSnapshot(); - }); - - test('resolves Object.values when using methods', () => { - const path = parse.expressionLast( - ['var foo = { boo: 1, foo: 2, bar(e) {} };', 'Object.values(foo);'].join( - '\n', - ), - ); - - expect(resolveObjectValuesToArray(path)).toMatchSnapshot(); - }); - - test('resolves Object.values but ignores duplicates', () => { - const path = parse.expressionLast( - [ - 'var bar = { doo: 4, doo: 5 }', - 'var foo = { boo: 1, foo: 2, doo: 1, ...bar };', - 'Object.values(foo);', - ].join('\n'), - ); - - expect(resolveObjectValuesToArray(path)).toMatchSnapshot(); - }); - - test('resolves Object.values but ignores duplicates with getter and setter', () => { - const path = parse.expressionLast( - ['var foo = { get x() {}, set x(a) {} };', 'Object.values(foo);'].join( - '\n', - ), - ); - - expect(resolveObjectValuesToArray(path)).toMatchSnapshot(); - }); - - test('does not resolve Object.values when using unresolvable spread', () => { - const path = parse.expressionLast( - ['var foo = { bar: 1, foo: 2, ...bar };', 'Object.values(foo);'].join( - '\n', - ), - ); - - expect(resolveObjectValuesToArray(path)).toBeNull(); - }); - - test('can resolve imported objects passed to Object.values', () => { - const path = parse.expressionLast( - `import foo from 'foo'; - Object.values(foo);`, - mockImporter, - ); - - expect(resolveObjectValuesToArray(path)).toMatchSnapshot(); - }); - - test('can resolve spreads from imported objects', () => { - const path = parse.expressionLast( - `import bar from 'bar'; - var abc = { foo: 'foo', baz: 'baz', ...bar }; - Object.values(abc);`, - mockImporter, - ); - - expect(resolveObjectValuesToArray(path)).toMatchSnapshot(); - }); - - test('can handle unresolved imported objects passed to Object.values', () => { - const path = parse.expressionLast( - `import foo from 'foo'; - Object.values(foo);`, - ); - - expect(resolveObjectValuesToArray(path)).toBe(null); - }); - - test('can handle unresolve spreads from imported objects', () => { - const path = parse.expressionLast( - `import bar from 'bar'; - var abc = { foo: 'foo', baz: 'baz', ...bar }; - Object.keys(abc);`, - ); - - expect(resolveObjectValuesToArray(path)).toBe(null); - }); - - test('can handle unresolve object value from imported objects', () => { - const path = parse.expressionLast( - `import bar from 'bar'; - var abc = { foo: 'foo', baz: bar }; - Object.keys(abc);`, - ); - - expect(resolveObjectValuesToArray(path)).toBe(null); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/resolveToModule-test.ts b/packages/react-docgen/src/utils/__tests__/resolveToModule-test.ts deleted file mode 100644 index fb14216b130..00000000000 --- a/packages/react-docgen/src/utils/__tests__/resolveToModule-test.ts +++ /dev/null @@ -1,111 +0,0 @@ -import { parse, makeMockImporter } from '../../../tests/utils'; -import resolveToModule from '../resolveToModule.js'; -import { describe, expect, test } from 'vitest'; - -describe('resolveToModule', () => { - const mockImporter = makeMockImporter({ - Foo: (stmtLast) => - stmtLast(` - import bar from 'Bar'; - export default bar; - `).get('declaration'), - - Bar: (stmtLast) => - stmtLast(` - import baz from 'Baz'; - export default baz; - `).get('declaration'), - }); - - test('resolves identifiers', () => { - const path = parse.expressionLast(` - var foo = require("Foo"); - foo; - `); - - expect(resolveToModule(path)).toBe('Foo'); - }); - - test('resolves function calls', () => { - const path = parse.expressionLast(` - var foo = require("Foo"); - foo(); - `); - - expect(resolveToModule(path)).toBe('Foo'); - }); - - test('resolves member expressions', () => { - const path = parse.expressionLast(` - var foo = require("Foo"); - foo.bar().baz; - `); - - expect(resolveToModule(path)).toBe('Foo'); - }); - - test('understands destructuring', () => { - const path = parse.expressionLast(` - var {foo} = require("Foo"); - foo; - `); - - expect(resolveToModule(path)).toBe('Foo'); - }); - - describe('ES6 import declarations', () => { - test('resolves ImportDefaultSpecifier', () => { - let path = parse.expressionLast(` - import foo from "Foo"; - foo; - `); - - expect(resolveToModule(path)).toBe('Foo'); - - path = parse.expressionLast(` - import foo, {createElement} from "Foo"; - foo; - `); - expect(resolveToModule(path)).toBe('Foo'); - }); - - test('resolves ImportSpecifier', () => { - const path = parse.expressionLast(` - import {foo, bar} from "Foo"; - bar; - `); - - expect(resolveToModule(path)).toBe('Foo'); - }); - - test('resolves aliased ImportSpecifier', () => { - const path = parse.expressionLast(` - import {foo, bar as baz} from "Foo"; - baz; - `); - - expect(resolveToModule(path)).toBe('Foo'); - }); - - test('resolves ImportNamespaceSpecifier', () => { - const path = parse.expressionLast(` - import * as foo from "Foo"; - foo; - `); - - expect(resolveToModule(path)).toBe('Foo'); - }); - - test('can resolve imports until one not expanded', () => { - const path = parse.expressionLast( - ` - import foo from "Foo"; - foo; - `, - mockImporter, - ); - - expect(resolveToModule(path)).toBe('Baz'); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/resolveToValue-test.ts b/packages/react-docgen/src/utils/__tests__/resolveToValue-test.ts deleted file mode 100644 index 1a00dde6fd6..00000000000 --- a/packages/react-docgen/src/utils/__tests__/resolveToValue-test.ts +++ /dev/null @@ -1,272 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { - AssignmentExpression, - CallExpression, - Identifier, - ExportNamedDeclaration, -} from '@babel/types'; -import { makeMockImporter, parse, parseTypescript } from '../../../tests/utils'; -import resolveToValue from '../resolveToValue.js'; -import { describe, expect, test } from 'vitest'; - -describe('resolveToValue', () => { - const mockImporter = makeMockImporter({ - Foo: (stmtLast) => - stmtLast(` - const baz = 3; - export { baz }; - `) - .get('specifiers')[0] - .get('local') as NodePath, - }); - - test('resolves simple variable declarations', () => { - const path = parse.expressionLast(['var foo = 42;', 'foo;'].join('\n')); - - expect(resolveToValue(path)).toMatchSnapshot(); - }); - - test('resolves object destructuring', () => { - const path = parse.expressionLast( - ['var {foo: {bar: baz}} = bar;', 'baz;'].join('\n'), - ); - - expect(resolveToValue(path)).toMatchSnapshot(); - }); - - test('handles RestElements properly', () => { - const path = parse.expressionLast( - ['var {foo: {bar}, ...baz} = bar;', 'baz;'].join('\n'), - ); - - expect(resolveToValue(path)).toMatchSnapshot(); - }); - - test('returns the original path if it cannot be resolved', () => { - const path = parse.expressionLast( - ['function foo() {}', 'foo()'].join('\n'), - ); - - expect(resolveToValue(path)).toBe(path); - }); - - test('resolves variable declarators to their init value', () => { - const path = parse.statement('var foo = 42;').get('declarations')[0]; - - expect(resolveToValue(path)).toMatchSnapshot(); - }); - - test('resolves to class declarations', () => { - const path = parse.expressionLast(` - class Foo {} - Foo; - `); - - expect(resolveToValue(path).node.type).toBe('ClassDeclaration'); - }); - - test('resolves to class function declaration', () => { - const path = parse.expressionLast(` - function foo() {} - foo; - `); - - expect(resolveToValue(path).node.type).toBe('FunctionDeclaration'); - }); - - describe('flow', () => { - test('resolves type cast expressions', () => { - const path = parse.expressionLast(` - function foo() {} - (foo: any); - `); - - expect(resolveToValue(path).node.type).toBe('FunctionDeclaration'); - }); - }); - - describe('typescript', () => { - test('resolves type as expressions', () => { - const path = parseTypescript.expressionLast(` - function foo() {} - (foo as any); - `); - - expect(resolveToValue(path).node.type).toBe('FunctionDeclaration'); - }); - - test('resolves type assertions', () => { - const path = parseTypescript.expressionLast(` - function foo() {} - ( foo); - `); - - expect(resolveToValue(path).node.type).toBe('FunctionDeclaration'); - }); - - test('resolves type alias', () => { - const path = parseTypescript.statement( - `let action: Action; - type Action = {};`, - ); - - expect( - resolveToValue( - path.get( - 'declarations.0.id.typeAnnotation.typeAnnotation.typeName', - ) as NodePath, - ).node.type, - ).toBe('TSTypeAliasDeclaration'); - }); - }); - - describe('assignments', () => { - test('resolves to assigned values', () => { - const path = parse.expressionLast( - ['var foo;', 'foo = 42;', 'foo;'].join('\n'), - ); - - expect(resolveToValue(path)).toMatchSnapshot(); - }); - - test('resolves to other assigned value if ref is in an assignment lhs', () => { - const path = parse.expressionLast( - ['var foo;', 'foo = 42;', 'foo = wrap(foo);'].join('\n'), - ); - - expect(resolveToValue(path.get('left'))).toMatchSnapshot(); - }); - - test('resolves to other assigned value if ref is in an assignment rhs', () => { - const path = parse.expressionLast( - ['var foo;', 'foo = 42;', 'foo = wrap(foo);'].join('\n'), - ); - - expect( - resolveToValue( - (path.get('right') as NodePath).get('arguments')[0], - ), - ).toMatchSnapshot(); - }); - }); - - describe('ImportDeclaration', () => { - test('resolves unresolvable default import references to the import declaration', () => { - const path = parse.expressionLast( - ['import foo from "Foo"', 'foo;'].join('\n'), - ); - const value = resolveToValue(path); - - expect(value.node.type).toBe('ImportDefaultSpecifier'); - }); - - test('resolves unresolvable named import references to the import declaration', () => { - const path = parse.expressionLast( - ['import {foo} from "Foo"', 'foo;'].join('\n'), - ); - const value = resolveToValue(path); - - expect(value.node.type).toBe('ImportSpecifier'); - }); - - test('resolves unresolvable aliased import references to the import declaration', () => { - const path = parse.expressionLast( - ['import {foo as bar} from "Foo"', 'bar;'].join('\n'), - ); - const value = resolveToValue(path); - - expect(value.node.type).toBe('ImportSpecifier'); - }); - - test('resolves unresolvable namespace import references to the import declaration', () => { - const path = parse.expressionLast( - ['import * as bar from "Foo"', 'bar;'].join('\n'), - ); - const value = resolveToValue(path); - - expect(value.node.type).toBe('ImportNamespaceSpecifier'); - }); - - test('resolves namespace import references to the import declaration', () => { - const path = parse.expressionLast( - `import * as bar from "Foo"; bar.baz`, - mockImporter, - ); - const value = resolveToValue(path); - - expect(value).toMatchSnapshot(); - }); - - test('resolves namespace import references to the import declaration', () => { - const path = parse.expressionLast( - `import * as bar from "Foo"; bar['baz']`, - mockImporter, - ); - const value = resolveToValue(path); - - expect(value).toMatchSnapshot(); - }); - - test('does not crash when resolving MemberExpression with non Identifiers', () => { - const path = parse.expressionLast( - `import * as bar from "Foo"; bar[()=>{}]`, - mockImporter, - ); - const value = resolveToValue(path); - - expect(value).toMatchSnapshot(); - }); - }); - - describe('MemberExpression', () => { - test("resolves a MemberExpression to it's init value", () => { - const path = parse.expressionLast( - ['var foo = { bar: 1 };', 'foo.bar;'].join('\n'), - ); - - expect(resolveToValue(path)).toMatchSnapshot(); - }); - - test('resolves a MemberExpression in the scope chain', () => { - const path = parse.expressionLast( - ['var foo = 1;', 'var bar = { baz: foo };', 'bar.baz;'].join('\n'), - ); - - expect(resolveToValue(path)).toMatchSnapshot(); - }); - - test('resolves a nested MemberExpression in the scope chain', () => { - const path = parse.expressionLast( - [ - 'var foo = { bar: 1 };', - 'var bar = { baz: foo.bar };', - 'bar.baz;', - ].join('\n'), - ); - - expect(resolveToValue(path)).toMatchSnapshot(); - }); - - test('returns the last resolvable MemberExpression', () => { - const path = parse.expressionLast( - [ - 'import foo from "bar";', - 'var bar = { baz: foo.bar };', - 'bar.baz;', - ].join('\n'), - ); - - expect(resolveToValue(path)).toMatchSnapshot(); - }); - - test('returns the path itself if it can not resolve it any further', () => { - const path = parse.expressionLast( - `var foo = {}; - foo.bar = 1; - foo.bar;`, - ); - - expect(resolveToValue(path)).toBe(path); - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/setPropDescription-test.ts b/packages/react-docgen/src/utils/__tests__/setPropDescription-test.ts deleted file mode 100644 index 2875de65cd3..00000000000 --- a/packages/react-docgen/src/utils/__tests__/setPropDescription-test.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { parse, makeMockImporter } from '../../../tests/utils'; -import setPropDescription from '../setPropDescription.js'; -import DocumentationBuilder from '../../Documentation'; -import type { default as DocumentationMock } from '../../__mocks__/Documentation'; -import type { ExpressionStatement } from '@babel/types'; -import { beforeEach, describe, expect, test, vi } from 'vitest'; - -vi.mock('../../Documentation.js'); - -describe('setPropDescription', () => { - let defaultDocumentation: DocumentationBuilder & DocumentationMock; - - beforeEach(() => { - defaultDocumentation = new DocumentationBuilder() as DocumentationBuilder & - DocumentationMock; - }); - - const mockImporter = makeMockImporter({ - foo: (stmtLast) => stmtLast(`export default 'foo';`).get('declaration'), - }); - - function getDescriptors(src: string, documentation = defaultDocumentation) { - const node = parse.expression(src).get('properties')[0]; - - setPropDescription(documentation, node); - - return documentation.descriptors; - } - - test('detects comments', () => { - const descriptors = getDescriptors(`{ - /** - * my description 3 - */ - - hal: boolean, - }`); - - expect(descriptors).toEqual({ - hal: { - description: 'my description 3', - }, - }); - }); - - test('does not update description if already set', () => { - defaultDocumentation.getPropDescriptor('foo').description = '12345678'; - - const descriptors = getDescriptors( - `{ - /** my description */ - foo: string, - }`, - defaultDocumentation, - ); - - expect(descriptors).toEqual({ - foo: { - description: '12345678', - }, - }); - }); - - test('sets an empty description if comment does not exist', () => { - const descriptors = getDescriptors(`{ - hal: boolean, - }`); - - expect(descriptors).toEqual({ - hal: { - description: '', - }, - }); - }); - - test('resolves computed props to imported values', () => { - const src = ` - ({ - /** - * my description 3 - */ - - [a]: boolean, - }); - import a from 'foo'; - `; - const node = parse - .statement(src, mockImporter) - .get('expression') - .get('properties')[0]; - - setPropDescription(defaultDocumentation, node); - - expect(defaultDocumentation.descriptors).toEqual({ - foo: { - description: 'my description 3', - }, - }); - }); -}); diff --git a/packages/react-docgen/src/utils/__tests__/unwrapBuiltinTSPropTypes-test.ts b/packages/react-docgen/src/utils/__tests__/unwrapBuiltinTSPropTypes-test.ts deleted file mode 100644 index cf7e7f0aa32..00000000000 --- a/packages/react-docgen/src/utils/__tests__/unwrapBuiltinTSPropTypes-test.ts +++ /dev/null @@ -1,99 +0,0 @@ -import type { TSTypeReference, VariableDeclaration } from '@babel/types'; -import { parseTypescript } from '../../../tests/utils'; -import unwrapBuiltinTSPropTypes from '../unwrapBuiltinTSPropTypes.js'; -import { describe, expect, test } from 'vitest'; -import type { NodePath } from '@babel/traverse'; - -describe('unwrapBuiltinTSPropTypes', () => { - test('React.PropsWithChildren', () => { - const path = parseTypescript - .statementLast( - `import React from 'react'; - var foo: React.PropsWithChildren`, - ) - .get( - 'declarations.0.id.typeAnnotation.typeAnnotation', - ) as NodePath; - - expect(unwrapBuiltinTSPropTypes(path)).toMatchSnapshot(); - }); - - test('React.PropsWithoutRef', () => { - const path = parseTypescript - .statementLast( - `import React from 'react'; - var foo: React.PropsWithoutRef`, - ) - .get( - 'declarations.0.id.typeAnnotation.typeAnnotation', - ) as NodePath; - - expect(unwrapBuiltinTSPropTypes(path)).toMatchSnapshot(); - }); - - test('React.PropsWithRef', () => { - const path = parseTypescript - .statementLast( - `import React from 'react'; - var foo: React.PropsWithRef`, - ) - .get( - 'declarations.0.id.typeAnnotation.typeAnnotation', - ) as NodePath; - - expect(unwrapBuiltinTSPropTypes(path)).toMatchSnapshot(); - }); - - test('multiple', () => { - const path = parseTypescript - .statementLast( - `import React from 'react'; - var foo: React.PropsWithChildren>`, - ) - .get( - 'declarations.0.id.typeAnnotation.typeAnnotation', - ) as NodePath; - - expect(unwrapBuiltinTSPropTypes(path)).toMatchSnapshot(); - }); - - test('does not follow reassignment', () => { - const path = parseTypescript - .statementLast( - `import React from 'react'; - type bar = React.PropsWithRef - var foo: React.PropsWithChildren`, - ) - .get( - 'declarations.0.id.typeAnnotation.typeAnnotation', - ) as NodePath; - - expect(unwrapBuiltinTSPropTypes(path)).toMatchSnapshot(); - }); - - test('with require', () => { - const path = parseTypescript - .statementLast( - `const React = require('react'); - var foo: React.PropsWithRef`, - ) - .get( - 'declarations.0.id.typeAnnotation.typeAnnotation', - ) as NodePath; - - expect(unwrapBuiltinTSPropTypes(path)).toMatchSnapshot(); - }); - - test('with named import', () => { - const path = parseTypescript - .statementLast( - `import { PropsWithRef } from 'react'; - var foo: PropsWithRef`, - ) - .get( - 'declarations.0.id.typeAnnotation.typeAnnotation', - ) as NodePath; - - expect(unwrapBuiltinTSPropTypes(path)).toMatchSnapshot(); - }); -}); diff --git a/packages/react-docgen/src/utils/docblock.ts b/packages/react-docgen/src/utils/docblock.ts deleted file mode 100644 index 96457c953cc..00000000000 --- a/packages/react-docgen/src/utils/docblock.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Helper functions to work with docblock comments. - */ - -import type { NodePath } from '@babel/traverse'; -import type { CommentBlock, CommentLine } from '@babel/types'; - -const DOCLET_PATTERN = /^@(\w+)(?:$|\s((?:[^](?!^@\w))*))/gim; - -function parseDocblock(str: string): string { - // Does not use \s in the regex as this would match also \n and conflicts - // with windows line endings. - return str.replace(/^[ \t]*\*[ \t]?/gm, '').trim(); -} - -const DOCBLOCK_HEADER = /^\*\s/; - -/** - * Given a path, this function returns the closest preceding docblock if it - * exists. - */ -export function getDocblock(path: NodePath, trailing = false): string | null { - let comments: Array = []; - - if (trailing && path.node.trailingComments) { - comments = path.node.trailingComments.filter( - (comment) => - comment.type === 'CommentBlock' && DOCBLOCK_HEADER.test(comment.value), - ); - } else if (path.node.leadingComments) { - comments = path.node.leadingComments.filter( - (comment) => - comment.type === 'CommentBlock' && DOCBLOCK_HEADER.test(comment.value), - ); - } - - if (comments.length > 0) { - return parseDocblock(comments[comments.length - 1]!.value); - } - - return null; -} - -/** - * Given a string, this functions returns an object with doclet names as keys - * and their "content" as values. - */ -export function getDoclets(str: string): Record { - const doclets = Object.create(null); - let match: RegExpExecArray | null; - - while ((match = DOCLET_PATTERN.exec(str))) { - doclets[match[1]!] = match[2] || true; - } - - return doclets; -} diff --git a/packages/react-docgen/src/utils/expressionTo.ts b/packages/react-docgen/src/utils/expressionTo.ts deleted file mode 100644 index a79e8943ed8..00000000000 --- a/packages/react-docgen/src/utils/expressionTo.ts +++ /dev/null @@ -1,99 +0,0 @@ -/*eslint no-loop-func: 0, no-use-before-define: 0*/ - -import resolveToValue from './resolveToValue.js'; -import type { NodePath } from '@babel/traverse'; -import type { Node } from '@babel/types'; - -/** - * Splits a MemberExpression or CallExpression into parts. - * E.g. foo.bar.baz becomes ['foo', 'bar', 'baz'] - */ -function toArray(path: NodePath): string[] { - const parts = [path]; - let result: string[] = []; - - while (parts.length > 0) { - path = parts.shift() as NodePath; - if (path.isCallExpression()) { - parts.push(path.get('callee')); - continue; - } else if (path.isMemberExpression()) { - parts.push(path.get('object')); - const property = path.get('property'); - - if (path.node.computed) { - const resolvedPath = resolveToValue(property); - - if (resolvedPath !== undefined) { - result = result.concat(toArray(resolvedPath)); - } else { - result.push(''); - } - } else if (property.isIdentifier()) { - result.push(property.node.name); - } else if (property.isPrivateName()) { - // new test - result.push(`#${property.get('id').node.name}`); - } - continue; - } else if (path.isIdentifier()) { - result.push(path.node.name); - continue; - } else if (path.isTSAsExpression()) { - const expression = path.get('expression'); - - if (expression.isIdentifier()) { - result.push(expression.node.name); - } - continue; - } else if (path.isLiteral() && path.node.extra?.raw) { - result.push(path.node.extra.raw as string); - continue; - } else if (path.isThisExpression()) { - result.push('this'); - continue; - } else if (path.isObjectExpression()) { - const properties = path.get('properties').map(function (property) { - if (property.isSpreadElement()) { - return `...${toString(property.get('argument'))}`; - } else if (property.isObjectProperty()) { - return ( - toString(property.get('key')) + - ': ' + - toString(property.get('value')) - ); - } else if (property.isObjectMethod()) { - return toString(property.get('key')) + ': '; - } else { - throw new Error('Unrecognized object property type'); - } - }); - - result.push('{' + properties.join(', ') + '}'); - continue; - } else if (path.isArrayExpression()) { - result.push( - '[' + - path - .get('elements') - .map(function (el) { - return toString(el); - }) - .join(', ') + - ']', - ); - continue; - } - } - - return result.reverse(); -} - -/** - * Creates a string representation of a member expression. - */ -function toString(path: NodePath): string { - return toArray(path).join('.'); -} - -export { toString as String, toArray as Array }; diff --git a/packages/react-docgen/src/utils/findComponentDefinition.ts b/packages/react-docgen/src/utils/findComponentDefinition.ts deleted file mode 100644 index ca27b9365e0..00000000000 --- a/packages/react-docgen/src/utils/findComponentDefinition.ts +++ /dev/null @@ -1,59 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { ComponentNode } from '../resolver/index.js'; -import isReactComponentClass from './isReactComponentClass.js'; -import isReactCreateClassCall from './isReactCreateClassCall.js'; -import isReactForwardRefCall from './isReactForwardRefCall.js'; -import isStatelessComponent from './isStatelessComponent.js'; -import normalizeClassDefinition from './normalizeClassDefinition.js'; -import resolveHOC from './resolveHOC.js'; -import resolveToValue from './resolveToValue.js'; - -function isComponentDefinition( - path: NodePath, -): path is NodePath { - return ( - isReactCreateClassCall(path) || - isReactComponentClass(path) || - isStatelessComponent(path) || - isReactForwardRefCall(path) - ); -} - -function resolveComponentDefinition( - definition: NodePath, -): NodePath | null { - if (isReactCreateClassCall(definition)) { - // return argument - const resolvedPath = resolveToValue(definition.get('arguments')[0]!); - - if (resolvedPath.isObjectExpression()) { - return resolvedPath; - } - } else if (isReactComponentClass(definition)) { - normalizeClassDefinition(definition); - - return definition; - } else if ( - isStatelessComponent(definition) || - isReactForwardRefCall(definition) - ) { - return definition; - } - - return null; -} - -export default function findComponentDefinition( - path: NodePath, -): NodePath | null { - let resolvedPath = path; - - if (!isComponentDefinition(resolvedPath)) { - resolvedPath = resolveToValue(resolveHOC(resolvedPath)); - if (!isComponentDefinition(resolvedPath)) { - return null; - } - } - - return resolveComponentDefinition(resolvedPath); -} diff --git a/packages/react-docgen/src/utils/findFunctionReturn.ts b/packages/react-docgen/src/utils/findFunctionReturn.ts deleted file mode 100644 index 492ae08201c..00000000000 --- a/packages/react-docgen/src/utils/findFunctionReturn.ts +++ /dev/null @@ -1,155 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import { visitors } from '@babel/traverse'; -import resolveToValue from './resolveToValue.js'; -import { ignore } from './traverse.js'; - -type Predicate = (path: NodePath) => path is T; - -interface TraverseState { - readonly predicate: Predicate; - resolvedReturnPath?: T; - readonly seen: WeakSet; -} - -const explodedVisitors = visitors.explode({ - Function: { enter: ignore }, - Class: { enter: ignore }, - ObjectExpression: { enter: ignore }, - ReturnStatement: { - enter: function (path, state) { - const argument = path.get('argument'); - - if (argument.hasNode()) { - const resolvedPath = resolvesToFinalValue( - argument, - state.predicate, - state.seen, - ); - - if (resolvedPath) { - state.resolvedReturnPath = resolvedPath; - path.stop(); - } - } - }, - }, -}); - -function resolvesToFinalValue( - path: NodePath, - predicate: Predicate, - seen: WeakSet, -): T | undefined { - // avoid returns with recursive function calls - if (seen.has(path)) { - return; - } - seen.add(path); - - // Is the path already passes then return it. - if (predicate(path)) { - return path; - } - - const resolvedPath = resolveToValue(path); - - // If the resolved path is already passing then no need to further check - // Only do this if the resolvedPath actually resolved something as otherwise we did this check already - if (resolvedPath.node !== path.node && predicate(resolvedPath)) { - return resolvedPath; - } - - // If the path points to a conditional expression, then we need to look only at - // the two possible paths - if (resolvedPath.isConditionalExpression()) { - return ( - resolvesToFinalValue(resolvedPath.get('consequent'), predicate, seen) || - resolvesToFinalValue(resolvedPath.get('alternate'), predicate, seen) - ); - } - - // If the path points to a logical expression (AND, OR, ...), then we need to look only at - // the two possible paths - if (resolvedPath.isLogicalExpression()) { - return ( - resolvesToFinalValue(resolvedPath.get('left'), predicate, seen) || - resolvesToFinalValue(resolvedPath.get('right'), predicate, seen) - ); - } - - // If we have a call expression, lets try to follow it - if (resolvedPath.isCallExpression()) { - const returnValue = findFunctionReturnWithCache( - resolveToValue(resolvedPath.get('callee')), - predicate, - seen, - ); - - if (returnValue) { - return returnValue; - } - } - - return; -} - -/** - * This can be used in two ways - * 1. Find the first return path that passes the predicate function - * (for example to check if a function is returning something) - * 2. Find all occurrences of return values - * For this the predicate acts more like a collector and always needs to return false - */ -function findFunctionReturnWithCache( - path: NodePath, - predicate: Predicate, - seen: WeakSet, -): T | undefined { - let functionPath: NodePath = path; - - if (functionPath.isObjectProperty()) { - functionPath = functionPath.get('value'); - } else if (functionPath.isClassProperty()) { - const classPropertyValue = functionPath.get('value'); - - if (classPropertyValue.hasNode()) { - functionPath = classPropertyValue; - } - } - - if (!functionPath.isFunction()) { - return; - } - - // skip traversing for ArrowFunctionExpressions with no block - if (path.isArrowFunctionExpression()) { - const body = path.get('body'); - - if (!body.isBlockStatement()) { - return resolvesToFinalValue(body, predicate, seen); - } - } - - const state: TraverseState = { - predicate, - seen, - }; - - path.traverse(explodedVisitors, state); - - return state.resolvedReturnPath; -} - -/** - * This can be used in two ways - * 1. Find the first return path that passes the predicate function - * (for example to check if a function is returning something) - * 2. Find all occurrences of return values - * For this the predicate acts more like a collector and always needs to return false - */ -export default function findFunctionReturn( - path: NodePath, - predicate: Predicate, -): T | undefined { - return findFunctionReturnWithCache(path, predicate, new WeakSet()); -} diff --git a/packages/react-docgen/src/utils/flowUtilityTypes.ts b/packages/react-docgen/src/utils/flowUtilityTypes.ts deleted file mode 100644 index f0c55aeb480..00000000000 --- a/packages/react-docgen/src/utils/flowUtilityTypes.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { GenericTypeAnnotation } from '@babel/types'; - -/** - * See `supportedUtilityTypes` for which types are supported and - * https://flow.org/en/docs/types/utilities/ for which types are available. - */ -export function isSupportedUtilityType( - path: NodePath, -): path is NodePath { - if (path.isGenericTypeAnnotation()) { - const idPath = path.get('id'); - - if (idPath.isIdentifier()) { - const name = idPath.node.name; - - return name === '$Exact' || name === '$ReadOnly'; - } - } - - return false; -} - -/** - * Unwraps well known utility types. For example: - * - * $ReadOnly => T - */ -export function unwrapUtilityType(path: NodePath): NodePath { - let resultPath: NodePath = path; - - while (isSupportedUtilityType(resultPath)) { - const typeParameters = resultPath.get('typeParameters'); - - if (!typeParameters.hasNode()) break; - - const firstParam = typeParameters.get('params')[0]; - - if (!firstParam) break; - - resultPath = firstParam; - } - - return resultPath; -} diff --git a/packages/react-docgen/src/utils/getClassMemberValuePath.ts b/packages/react-docgen/src/utils/getClassMemberValuePath.ts deleted file mode 100644 index cae60290cb2..00000000000 --- a/packages/react-docgen/src/utils/getClassMemberValuePath.ts +++ /dev/null @@ -1,45 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { - ClassDeclaration, - ClassExpression, - ClassMethod, - ClassProperty, - Expression, -} from '@babel/types'; -import getNameOrValue from './getNameOrValue.js'; - -export default function getClassMemberValuePath( - classDefinition: NodePath, - memberName: string, -): NodePath | null { - const classMember = classDefinition - .get('body') - .get('body') - .find((memberPath) => { - if ( - (memberPath.isClassMethod() && memberPath.node.kind !== 'set') || - memberPath.isClassProperty() - ) { - const key = (memberPath as NodePath).get( - 'key', - ); - - return ( - (!memberPath.node.computed || key.isLiteral()) && - getNameOrValue(key) === memberName - ); - } - - return false; - }); - - if (classMember) { - // For ClassProperty we return the value and for ClassMethod - // we return itself - return classMember.isClassMethod() - ? classMember - : (classMember.get('value') as NodePath); - } - - return null; -} diff --git a/packages/react-docgen/src/utils/getFlowType.ts b/packages/react-docgen/src/utils/getFlowType.ts deleted file mode 100644 index 54e64f4fba4..00000000000 --- a/packages/react-docgen/src/utils/getFlowType.ts +++ /dev/null @@ -1,538 +0,0 @@ -import getPropertyName from './getPropertyName.js'; -import printValue from './printValue.js'; -import getTypeAnnotation from '../utils/getTypeAnnotation.js'; -import resolveToValue from '../utils/resolveToValue.js'; -import { resolveObjectToNameArray } from '../utils/resolveObjectKeysToArray.js'; -import type { TypeParameters } from '../utils/getTypeParameters.js'; -import getTypeParameters from '../utils/getTypeParameters.js'; -import type { - ElementsType, - FunctionSignatureType, - LiteralType, - ObjectSignatureType, - SimpleType, - TypeDescriptor, -} from '../Documentation.js'; -import type { NodePath } from '@babel/traverse'; -import type { - ArrayTypeAnnotation, - BooleanLiteralTypeAnnotation, - FlowType, - FunctionTypeAnnotation, - GenericTypeAnnotation, - Identifier, - IndexedAccessType, - InterfaceDeclaration, - IntersectionTypeAnnotation, - Node, - NullableTypeAnnotation, - NumberLiteralTypeAnnotation, - ObjectTypeAnnotation, - StringLiteralTypeAnnotation, - TupleTypeAnnotation, - TypeofTypeAnnotation, - TypeParameterDeclaration, - UnionTypeAnnotation, -} from '@babel/types'; -import { getDocblock } from './docblock.js'; - -const flowTypes: Record = { - AnyTypeAnnotation: 'any', - BooleanTypeAnnotation: 'boolean', - MixedTypeAnnotation: 'mixed', - NullLiteralTypeAnnotation: 'null', - NumberTypeAnnotation: 'number', - StringTypeAnnotation: 'string', - VoidTypeAnnotation: 'void', - EmptyTypeAnnotation: 'empty', -}; - -const flowLiteralTypes = { - BooleanLiteralTypeAnnotation: 1, - NumberLiteralTypeAnnotation: 1, - StringLiteralTypeAnnotation: 1, -}; - -const namedTypes: Record< - string, - ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - path: NodePath, - typeParams: TypeParameters | null, - ) => TypeDescriptor | null -> = { - ArrayTypeAnnotation: handleArrayTypeAnnotation, - GenericTypeAnnotation: handleGenericTypeAnnotation, - ObjectTypeAnnotation: handleObjectTypeAnnotation, - InterfaceDeclaration: handleInterfaceDeclaration, - UnionTypeAnnotation: handleUnionTypeAnnotation, - NullableTypeAnnotation: handleNullableTypeAnnotation, - FunctionTypeAnnotation: handleFunctionTypeAnnotation, - IntersectionTypeAnnotation: handleIntersectionTypeAnnotation, - TupleTypeAnnotation: handleTupleTypeAnnotation, - TypeofTypeAnnotation: handleTypeofTypeAnnotation, - IndexedAccessType: handleIndexedAccessType, -}; - -function getFlowTypeWithRequirements( - path: NodePath, - typeParams: TypeParameters | null, -): TypeDescriptor { - const type = getFlowTypeWithResolvedTypes(path, typeParams); - - type.required = - 'optional' in path.parentPath.node ? !path.parentPath.node.optional : true; - - return type; -} - -function handleKeysHelper( - path: NodePath, -): ElementsType | null { - const typeParams = path.get('typeParameters'); - - if (!typeParams.hasNode()) { - return null; - } - - let value: NodePath | undefined = - typeParams.get('params')[0]; - - if (!value) { - return null; - } - - if (value.isTypeofTypeAnnotation()) { - value = value.get('argument').get('id') as NodePath< - Node | null | undefined - >; - } else if (!value.isObjectTypeAnnotation()) { - value = value.get('id') as NodePath; - } - - const resolvedPath = value.hasNode() ? resolveToValue(value) : value; - - if ( - resolvedPath.isObjectExpression() || - resolvedPath.isObjectTypeAnnotation() - ) { - const keys = resolveObjectToNameArray(resolvedPath, true); - - if (keys) { - return { - name: 'union', - raw: printValue(path), - elements: keys.map((key) => ({ name: 'literal', value: key })), - }; - } - } - - return null; -} - -function handleArrayTypeAnnotation( - path: NodePath, - typeParams: TypeParameters | null, -): ElementsType { - return { - name: 'Array', - elements: [ - getFlowTypeWithResolvedTypes(path.get('elementType'), typeParams), - ], - raw: printValue(path), - }; -} - -function handleGenericTypeAnnotation( - path: NodePath, - typeParams: TypeParameters | null, -): TypeDescriptor | null { - const id = path.get('id'); - const typeParameters = path.get('typeParameters'); - - if (id.isIdentifier({ name: '$Keys' }) && typeParameters.hasNode()) { - return handleKeysHelper(path); - } - - let type: TypeDescriptor; - - if (id.isQualifiedTypeIdentifier()) { - const qualification = id.get('qualification'); - - if (qualification.isIdentifier({ name: 'React' })) { - type = { - name: `${qualification.node.name}${id.node.id.name}`, - raw: printValue(id), - }; - } else { - type = { name: printValue(id).replace(/<.*>$/, '') }; - } - } else { - type = { name: (id as NodePath).node.name }; - } - - const resolvedPath = - (typeParams && typeParams[type.name]) || resolveToValue(path.get('id')); - - if (typeParameters.hasNode() && resolvedPath.has('typeParameters')) { - typeParams = getTypeParameters( - resolvedPath.get('typeParameters') as NodePath, - typeParameters, - typeParams, - ); - } - - if ( - typeParams && - typeParams[type.name] && - typeParams[type.name]!.isGenericTypeAnnotation() - ) { - return type; - } - - if (typeParams && typeParams[type.name]) { - type = getFlowTypeWithResolvedTypes( - resolvedPath as NodePath, - typeParams, - ); - } - - if (resolvedPath && resolvedPath.has('right')) { - type = getFlowTypeWithResolvedTypes( - resolvedPath.get('right') as NodePath, - typeParams, - ); - } else if (typeParameters.hasNode()) { - const params = typeParameters.get('params'); - - type = { - ...(type as SimpleType), - elements: params.map((param) => - getFlowTypeWithResolvedTypes(param, typeParams), - ), - raw: printValue(path), - }; - } - - return type; -} - -function handleObjectTypeAnnotation( - path: NodePath, - typeParams: TypeParameters | null, -): TypeDescriptor { - const type: ObjectSignatureType = { - name: 'signature', - type: 'object', - raw: printValue(path), - signature: { properties: [] }, - }; - - const callProperties = path.get('callProperties'); - - if (Array.isArray(callProperties)) { - callProperties.forEach((param) => { - type.signature.constructor = getFlowTypeWithResolvedTypes( - param.get('value'), - typeParams, - ); - }); - } - - const indexers = path.get('indexers'); - - if (Array.isArray(indexers)) { - indexers.forEach((param) => { - const typeDescriptor: (typeof type.signature.properties)[number] = { - key: getFlowTypeWithResolvedTypes(param.get('key'), typeParams), - value: getFlowTypeWithRequirements(param.get('value'), typeParams), - }; - const docblock = getDocblock(param); - - if (docblock) { - typeDescriptor.description = docblock; - } - - type.signature.properties.push(typeDescriptor); - }); - } - - path.get('properties').forEach((param) => { - if (param.isObjectTypeProperty()) { - const typeDescriptor: (typeof type.signature.properties)[number] = { - // For ObjectTypeProperties `getPropertyName` always returns string - key: getPropertyName(param) as string, - value: getFlowTypeWithRequirements(param.get('value'), typeParams), - }; - const docblock = getDocblock(param); - - if (docblock) { - typeDescriptor.description = docblock; - } - - type.signature.properties.push(typeDescriptor); - } else if (param.isObjectTypeSpreadProperty()) { - let spreadObject = resolveToValue(param.get('argument')); - - if (spreadObject.isGenericTypeAnnotation()) { - const typeAlias = resolveToValue(spreadObject.get('id')); - - if ( - typeAlias.isTypeAlias() && - typeAlias.get('right').isObjectTypeAnnotation() - ) { - spreadObject = resolveToValue(typeAlias.get('right')); - } - } - - if (spreadObject.isObjectTypeAnnotation()) { - const props = handleObjectTypeAnnotation( - spreadObject, - typeParams, - ) as ObjectSignatureType; - - type.signature.properties.push(...props.signature.properties); - } - } - }); - - return type; -} - -function handleInterfaceDeclaration( - path: NodePath, -): SimpleType { - // Interfaces are handled like references which would be documented separately, - // rather than inlined like type aliases. - return { - name: path.node.id.name, - }; -} - -function handleUnionTypeAnnotation( - path: NodePath, - typeParams: TypeParameters | null, -): ElementsType { - return { - name: 'union', - raw: printValue(path), - elements: path - .get('types') - .map((subType) => getFlowTypeWithResolvedTypes(subType, typeParams)), - }; -} - -function handleIntersectionTypeAnnotation( - path: NodePath, - typeParams: TypeParameters | null, -): ElementsType { - return { - name: 'intersection', - raw: printValue(path), - elements: path - .get('types') - .map((subType) => getFlowTypeWithResolvedTypes(subType, typeParams)), - }; -} - -function handleNullableTypeAnnotation( - path: NodePath, - typeParams: TypeParameters | null, -): TypeDescriptor | null { - const typeAnnotation = getTypeAnnotation(path); - - if (!typeAnnotation) return null; - - const type = getFlowTypeWithResolvedTypes(typeAnnotation, typeParams); - - type.nullable = true; - - return type; -} - -function handleFunctionTypeAnnotation( - path: NodePath, - typeParams: TypeParameters | null, -): FunctionSignatureType { - const type: FunctionSignatureType = { - name: 'signature', - type: 'function', - raw: printValue(path), - signature: { - arguments: [], - return: getFlowTypeWithResolvedTypes(path.get('returnType'), typeParams), - }, - }; - - path.get('params').forEach((param) => { - const typeAnnotation = getTypeAnnotation(param); - - type.signature.arguments.push({ - name: param.node.name ? param.node.name.name : '', - type: typeAnnotation - ? getFlowTypeWithResolvedTypes(typeAnnotation, typeParams) - : undefined, - }); - }); - - const rest = path.get('rest'); - - if (rest.hasNode()) { - const typeAnnotation = getTypeAnnotation(rest); - - type.signature.arguments.push({ - name: rest.node.name ? rest.node.name.name : '', - type: typeAnnotation - ? getFlowTypeWithResolvedTypes(typeAnnotation, typeParams) - : undefined, - rest: true, - }); - } - - return type; -} - -function handleTupleTypeAnnotation( - path: NodePath, - typeParams: TypeParameters | null, -): ElementsType { - const type: ElementsType = { - name: 'tuple', - raw: printValue(path), - elements: [], - }; - - path.get('types').forEach((param) => { - type.elements.push(getFlowTypeWithResolvedTypes(param, typeParams)); - }); - - return type; -} - -function handleTypeofTypeAnnotation( - path: NodePath, - typeParams: TypeParameters | null, -): TypeDescriptor { - return getFlowTypeWithResolvedTypes(path.get('argument'), typeParams); -} - -function handleIndexedAccessType( - path: NodePath, - typeParams: TypeParameters | null, -): SimpleType { - const objectType = getFlowTypeWithResolvedTypes( - path.get('objectType'), - typeParams, - ) as ObjectSignatureType; - const indexType = getFlowTypeWithResolvedTypes( - path.get('indexType'), - typeParams, - ) as LiteralType; - - // We only get the signature if the objectType is a type (vs interface) - if (!objectType.signature) { - return { - name: `${objectType.name}[${ - indexType.value ? indexType.value.toString() : indexType.name - }]`, - raw: printValue(path), - }; - } - - const resolvedType = objectType.signature.properties.find((p) => { - // indexType.value = "'foo'" - return indexType.value && p.key === indexType.value.replace(/['"]+/g, ''); - }); - - if (!resolvedType) { - return { name: 'unknown' }; - } - - return { - name: resolvedType.value.name, - raw: printValue(path), - }; -} - -let visitedTypes: Record = {}; - -function getFlowTypeWithResolvedTypes( - path: NodePath, - typeParams: TypeParameters | null, -): TypeDescriptor { - let type: TypeDescriptor | null = null; - const parent = path.parentPath; - - const isTypeAlias = parent.isTypeAlias(); - - // When we see a TypeAlias mark it as visited so that the next - // call of this function does not run into an endless loop - if (isTypeAlias) { - const visitedType = visitedTypes[parent.node.id.name]; - - if (visitedType === true) { - // if we are currently visiting this node then just return the name - // as we are starting to endless loop - return { name: parent.node.id.name }; - } else if (typeof visitedType === 'object') { - // if we already resolved the type simple return it - return visitedType; - } - // mark the type as visited - visitedTypes[parent.node.id.name] = true; - } - - if (path.node.type in flowTypes) { - type = { name: flowTypes[path.node.type]! }; - } else if (path.node.type in flowLiteralTypes) { - type = { - name: 'literal', - value: - (path.node.extra?.raw as string) || - `${ - ( - path as NodePath< - | BooleanLiteralTypeAnnotation - | NumberLiteralTypeAnnotation - | StringLiteralTypeAnnotation - > - ).node.value - }`, - }; - } else if (path.node.type in namedTypes) { - type = namedTypes[path.node.type]!(path, typeParams); - } - - if (!type) { - type = { name: 'unknown' }; - } - - if (isTypeAlias) { - // mark the type as unvisited so that further calls can resolve the type again - visitedTypes[parent.node.id.name] = type; - } - - return type; -} - -/** - * Tries to identify the flow type by inspecting the path for known - * flow type names. This method doesn't check whether the found type is actually - * existing. It simply assumes that a match is always valid. - * - * If there is no match, "unknown" is returned. - */ -export default function getFlowType( - path: NodePath, - typeParams: TypeParameters | null = null, -): TypeDescriptor { - // Empty visited types before an after run - // Before: in case the detection threw and we rerun again - // After: cleanup memory after we are done here - visitedTypes = {}; - const type = getFlowTypeWithResolvedTypes(path, typeParams); - - visitedTypes = {}; - - return type; -} diff --git a/packages/react-docgen/src/utils/getMemberExpressionRoot.ts b/packages/react-docgen/src/utils/getMemberExpressionRoot.ts deleted file mode 100644 index 4758b744e7c..00000000000 --- a/packages/react-docgen/src/utils/getMemberExpressionRoot.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { Expression, MemberExpression } from '@babel/types'; - -/** - * Returns the path to the first part of the MemberExpression. I.e. given a - * path representing - * - * foo.bar.baz - * - * it returns the path of/to `foo`. - */ -export default function getMemberExpressionRoot( - memberExpressionPath: NodePath, -): NodePath { - let path: NodePath = memberExpressionPath; - - while (path.isMemberExpression()) { - path = path.get('object'); - } - - return path; -} diff --git a/packages/react-docgen/src/utils/getMemberExpressionValuePath.ts b/packages/react-docgen/src/utils/getMemberExpressionValuePath.ts deleted file mode 100644 index c2a73e681d2..00000000000 --- a/packages/react-docgen/src/utils/getMemberExpressionValuePath.ts +++ /dev/null @@ -1,124 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import { visitors } from '@babel/traverse'; -import type { Expression } from '@babel/types'; -import getNameOrValue from './getNameOrValue.js'; -import { String as toString } from './expressionTo.js'; -import isReactForwardRefCall from './isReactForwardRefCall.js'; - -function resolveName(path: NodePath): string | undefined { - if (path.isVariableDeclaration()) { - const declarations = path.get('declarations'); - - if (declarations.length > 1) { - throw new TypeError( - 'Got unsupported VariableDeclaration. VariableDeclaration must only ' + - 'have a single VariableDeclarator. Got ' + - declarations.length + - ' declarations.', - ); - } - // VariableDeclarator always has at least one declaration, hence the non-null-assertion - const id = declarations[0]!.get('id'); - - if (id.isIdentifier()) { - return id.node.name; - } - - return; - } - - if (path.isFunctionDeclaration()) { - const id = path.get('id'); - - if (id.isIdentifier()) { - return id.node.name; - } - - return; - } - - if ( - path.isFunctionExpression() || - path.isArrowFunctionExpression() || - path.isTaggedTemplateExpression() || - path.isCallExpression() || - isReactForwardRefCall(path) - ) { - let currentPath: NodePath = path; - - while (currentPath.parentPath) { - if (currentPath.parentPath.isVariableDeclarator()) { - const id = currentPath.parentPath.get('id'); - - if (id.isIdentifier()) { - return id.node.name; - } - - return; - } - - currentPath = currentPath.parentPath; - } - - return; - } - - throw new TypeError( - 'Attempted to resolveName for an unsupported path. resolveName does not accept ' + - path.node.type + - '".', - ); -} - -interface TraverseState { - readonly memberName: string; - readonly localName: string; - result: NodePath | null; -} - -const explodedVisitors = visitors.explode({ - AssignmentExpression: { - enter: function (path, state) { - const memberPath = path.get('left'); - - if (!memberPath.isMemberExpression()) { - return; - } - const property = memberPath.get('property'); - - if ( - ((!memberPath.node.computed && property.isIdentifier()) || - property.isStringLiteral() || - property.isNumericLiteral()) && - getNameOrValue(property) === state.memberName && - toString(memberPath.get('object')) === state.localName - ) { - state.result = path.get('right'); - path.stop(); - } - }, - }, -}); - -export default function getMemberExpressionValuePath( - variableDefinition: NodePath, - memberName: string, -): NodePath | null { - const localName = resolveName(variableDefinition); - - if (!localName) { - // likely an immediately exported and therefore nameless/anonymous node - // passed in - return null; - } - - const state: TraverseState = { - localName, - memberName, - result: null, - }; - - variableDefinition.hub.file.traverse(explodedVisitors, state); - - return state.result; -} diff --git a/packages/react-docgen/src/utils/getMemberValuePath.ts b/packages/react-docgen/src/utils/getMemberValuePath.ts deleted file mode 100644 index e2dee83df70..00000000000 --- a/packages/react-docgen/src/utils/getMemberValuePath.ts +++ /dev/null @@ -1,127 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import getClassMemberValuePath from './getClassMemberValuePath.js'; -import getMemberExpressionValuePath from './getMemberExpressionValuePath.js'; -import getPropertyValuePath from './getPropertyValuePath.js'; -import resolveFunctionDefinitionToReturnValue from '../utils/resolveFunctionDefinitionToReturnValue.js'; -import type { - CallExpression, - ClassDeclaration, - ClassExpression, - ClassMethod, - Expression, - ObjectExpression, - ObjectMethod, - TaggedTemplateExpression, - VariableDeclaration, -} from '@babel/types'; -import type { StatelessComponentNode } from '../resolver/index.js'; - -type SupportedNodes = - | CallExpression - | ClassDeclaration - | ClassExpression - | ObjectExpression - | StatelessComponentNode - | TaggedTemplateExpression - | VariableDeclaration; - -const postprocessPropTypes = ( - path: NodePath, -): NodePath | null => - path.isFunction() ? resolveFunctionDefinitionToReturnValue(path) : path; - -const POSTPROCESS_MEMBERS = new Map([['propTypes', postprocessPropTypes]]); - -const SUPPORTED_DEFINITION_TYPES = [ - // potential stateless function component - 'ArrowFunctionExpression', - /** - * Adds support for libraries such as - * [system-components]{@link https://jxnblk.com/styled-system/system-components} that use - * CallExpressions to generate components. - * - * While react-docgen's built-in resolvers do not support resolving - * CallExpressions definitions, third-party resolvers (such as - * https://github.com/Jmeyering/react-docgen-annotation-resolver) could be - * used to add these definitions. - */ - 'CallExpression', - 'ClassDeclaration', - 'ClassExpression', - // potential stateless function component - 'FunctionDeclaration', - // potential stateless function component - 'FunctionExpression', - 'ObjectExpression', - // potential stateless function component - 'ObjectMethod', - /** - * Adds support for libraries such as - * [styled components]{@link https://github.com/styled-components} that use - * TaggedTemplateExpression's to generate components. - * - * While react-docgen's built-in resolvers do not support resolving - * TaggedTemplateExpression definitions, third-party resolvers (such as - * https://github.com/Jmeyering/react-docgen-annotation-resolver) could be - * used to add these definitions. - */ - 'TaggedTemplateExpression', - 'VariableDeclaration', -]; - -export function isSupportedDefinitionType( - path: NodePath, -): path is NodePath { - return SUPPORTED_DEFINITION_TYPES.includes(path.node.type); -} - -/** - * This is a helper method for handlers to make it easier to work either with - * an ObjectExpression from `React.createClass` class or with a class - * definition. - * - * Given a path and a name, this function will either return the path of the - * property value if the path is an ObjectExpression, or the value of the - * ClassProperty/MethodDefinition if it is a class definition (declaration or - * expression). - * - * It also normalizes the names so that e.g. `defaultProps` and - * `getDefaultProps` can be used interchangeably. - */ -export default function getMemberValuePath( - componentDefinition: NodePath, - memberName: string, -): NodePath | null { - let result: NodePath | null; - - if (componentDefinition.isObjectExpression()) { - result = getPropertyValuePath(componentDefinition, memberName); - if (!result && memberName === 'defaultProps') { - result = getPropertyValuePath(componentDefinition, 'getDefaultProps'); - } - } else if ( - componentDefinition.isClassDeclaration() || - componentDefinition.isClassExpression() - ) { - result = getClassMemberValuePath(componentDefinition, memberName); - if (!result && memberName === 'defaultProps') { - result = getClassMemberValuePath(componentDefinition, 'getDefaultProps'); - } - } else { - result = getMemberExpressionValuePath(componentDefinition, memberName); - if (!result && memberName === 'defaultProps') { - result = getMemberExpressionValuePath( - componentDefinition, - 'getDefaultProps', - ); - } - } - - const postprocessMethod = POSTPROCESS_MEMBERS.get(memberName); - - if (result && postprocessMethod) { - result = postprocessMethod(result); - } - - return result; -} diff --git a/packages/react-docgen/src/utils/getMembers.ts b/packages/react-docgen/src/utils/getMembers.ts deleted file mode 100644 index 53734f024ef..00000000000 --- a/packages/react-docgen/src/utils/getMembers.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { Expression, PrivateName } from '@babel/types'; - -interface MemberDescriptor { - path: NodePath; - computed: boolean; - argumentPaths: NodePath[]; -} - -/** - * Given a "nested" Member/CallExpression, e.g. - * - * foo.bar()[baz][42] - * - * this returns a list of "members". In this example it would be something like - * [ - * {path: NodePath, arguments: NodePath, computed: false}, - * {path: NodePath, arguments: null, computed: true}, - * {path: NodePath<42>, arguments: null, computed: false} - * ] - */ -export default function getMembers( - path: NodePath, - includeRoot = false, -): MemberDescriptor[] { - const result: MemberDescriptor[] = []; - let argumentPaths: NodePath[] = []; - let resultPath: MemberDescriptor['path'] = path as NodePath; - - while (true) { - if (resultPath.isMemberExpression()) { - const property = resultPath.get('property'); - - result.push({ - path: property, - computed: resultPath.node.computed, - argumentPaths, - }); - argumentPaths = []; - resultPath = resultPath.get('object'); - } else if (resultPath.isCallExpression()) { - const callee = resultPath.get('callee'); - - if (callee.isExpression()) { - argumentPaths = resultPath.get('arguments'); - resultPath = callee; - } else { - break; - } - } else { - break; - } - } - if (includeRoot && result.length > 0) { - result.push({ - path: resultPath, - computed: false, - argumentPaths, - }); - } - - return result.reverse(); -} diff --git a/packages/react-docgen/src/utils/getMethodDocumentation.ts b/packages/react-docgen/src/utils/getMethodDocumentation.ts deleted file mode 100644 index 3dc0162ea53..00000000000 --- a/packages/react-docgen/src/utils/getMethodDocumentation.ts +++ /dev/null @@ -1,253 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { - AssignmentExpression, - ClassMethod, - ClassPrivateMethod, - ClassProperty, - Function as FunctionType, - ObjectMethod, - ObjectProperty, -} from '@babel/types'; -import { getDocblock } from './docblock.js'; -import getFlowType from './getFlowType.js'; -import getTSType from './getTSType.js'; -import getParameterName from './getParameterName.js'; -import getPropertyName from './getPropertyName.js'; -import getTypeAnnotation from './getTypeAnnotation.js'; -import resolveToValue from './resolveToValue.js'; -import printValue from './printValue.js'; -import type { - MethodDescriptor, - MethodModifier, - MethodParameter, - MethodReturn, - TypeDescriptor, -} from '../Documentation.js'; - -export type MethodNodePath = - | NodePath - | NodePath - | NodePath - | NodePath - | NodePath - | NodePath; - -function getMethodFunctionExpression( - methodPath: MethodNodePath, -): NodePath | null { - if (methodPath.isClassMethod() || methodPath.isObjectMethod()) { - return methodPath; - } - - const potentialFunctionExpression = methodPath.isAssignmentExpression() - ? methodPath.get('right') - : (methodPath.get('value') as NodePath); - - const functionExpression = resolveToValue(potentialFunctionExpression); - - if (functionExpression.isFunction()) { - return functionExpression; - } - - return null; -} - -function getMethodParamOptional( - path: NodePath, -): boolean { - let identifier: NodePath = path; - - if (identifier.isTSParameterProperty()) { - identifier = identifier.get('parameter'); - } - if (identifier.isAssignmentPattern()) { - // A default value always makes the param optional - return true; - } - - return identifier.isIdentifier() ? Boolean(identifier.node.optional) : false; -} - -function getMethodParamsDoc(methodPath: MethodNodePath): MethodParameter[] { - const params: MethodParameter[] = []; - const functionExpression = getMethodFunctionExpression(methodPath); - - if (functionExpression) { - // Extract param types. - functionExpression.get('params').forEach((paramPath) => { - let type: TypeDescriptor | null = null; - const typePath = getTypeAnnotation(paramPath); - - if (typePath) { - if (typePath.isFlowType()) { - type = getFlowType(typePath, null); - if (typePath.isGenericTypeAnnotation()) { - type.alias = printValue(typePath.get('id')); - } - } else if (typePath.isTSType()) { - type = getTSType(typePath, null); - if (typePath.isTSTypeReference()) { - type.alias = printValue(typePath.get('typeName')); - } - } - } - - const param = { - name: getParameterName(paramPath), - optional: getMethodParamOptional(paramPath), - type, - }; - - params.push(param); - }); - } - - return params; -} - -// Extract flow return type. -function getMethodReturnDoc(methodPath: MethodNodePath): MethodReturn | null { - const functionExpression = getMethodFunctionExpression(methodPath); - - if (functionExpression && functionExpression.node.returnType) { - const returnType = getTypeAnnotation(functionExpression.get('returnType')); - - if (!returnType) { - return null; - } - - if (returnType.isFlowType()) { - return { type: getFlowType(returnType, null) }; - } else if (returnType.isTSType()) { - return { type: getTSType(returnType, null) }; - } - } - - return null; -} - -function getMethodModifiers( - methodPath: MethodNodePath, - options: { isStatic?: boolean }, -): MethodModifier[] { - if (methodPath.isAssignmentExpression()) { - return ['static']; - } - - // Otherwise this is a method/property node - - const modifiers: MethodModifier[] = []; - - if ( - options.isStatic === true || - ((methodPath.isClassProperty() || methodPath.isClassMethod()) && - methodPath.node.static) - ) { - modifiers.push('static'); - } - - const functionExpression = getMethodFunctionExpression(methodPath); - - if (functionExpression) { - if ( - functionExpression.isClassMethod() || - functionExpression.isObjectMethod() - ) { - if ( - functionExpression.node.kind === 'get' || - functionExpression.node.kind === 'set' - ) { - modifiers.push(functionExpression.node.kind); - } - } - - if (functionExpression.node.generator) { - modifiers.push('generator'); - } - if (functionExpression.node.async) { - modifiers.push('async'); - } - } - - return modifiers; -} - -function getMethodName( - methodPath: Exclude>, -): string | null { - if (methodPath.isAssignmentExpression()) { - const left = methodPath.get('left'); - - if (left.isMemberExpression()) { - const property = left.get('property'); - - if (!left.node.computed && property.isIdentifier()) { - return property.node.name; - } - if (property.isStringLiteral() || property.isNumericLiteral()) { - return String(property.node.value); - } - } - - return null; - } - - return getPropertyName(methodPath); -} - -function getMethodAccessibility( - methodPath: MethodNodePath, -): 'private' | 'protected' | 'public' | null { - if (methodPath.isClassMethod() || methodPath.isClassProperty()) { - return methodPath.node.accessibility || null; - } - - // Otherwise this is a object method/property or assignment expression - return null; -} - -function getMethodDocblock(methodPath: MethodNodePath): string | null { - if (methodPath.isAssignmentExpression()) { - let path: NodePath | null = methodPath; - - do { - path = path.parentPath; - } while (path && !path.isExpressionStatement()); - - if (path) { - return getDocblock(path); - } - - return null; - } - - // Otherwise this is a method/property node - return getDocblock(methodPath); -} - -// Gets the documentation object for a component method. -// Component methods may be represented as class/object method/property nodes -// or as assignment expression of the form `Component.foo = function() {}` -export default function getMethodDocumentation( - methodPath: MethodNodePath, - options: { isStatic?: boolean } = {}, -): MethodDescriptor | null { - if ( - getMethodAccessibility(methodPath) === 'private' || - methodPath.isClassPrivateMethod() - ) { - return null; - } - - const name = getMethodName(methodPath); - - if (!name) return null; - - return { - name, - docblock: getMethodDocblock(methodPath), - modifiers: getMethodModifiers(methodPath, options), - params: getMethodParamsDoc(methodPath), - returns: getMethodReturnDoc(methodPath), - }; -} diff --git a/packages/react-docgen/src/utils/getNameOrValue.ts b/packages/react-docgen/src/utils/getNameOrValue.ts deleted file mode 100644 index c78c91ea178..00000000000 --- a/packages/react-docgen/src/utils/getNameOrValue.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import printValue from './printValue.js'; - -/** - * If node is an Identifier, it returns its name. If it is a literal, it returns - * its value. - */ -export default function getNameOrValue( - path: NodePath, -): boolean | number | string | null { - if (path.isIdentifier()) { - return path.node.name; - } else if (path.isQualifiedTypeIdentifier() || path.isTSQualifiedName()) { - return printValue(path); - } else if ( - path.isStringLiteral() || - path.isNumericLiteral() || - path.isBooleanLiteral() - ) { - return path.node.value; - } else if (path.isRegExpLiteral()) { - return path.node.pattern; - } else if (path.isNullLiteral()) { - return null; - } - - throw new TypeError( - `Argument must be Identifier, Literal, QualifiedTypeIdentifier or TSQualifiedName. Received '${path.node.type}'`, - ); -} diff --git a/packages/react-docgen/src/utils/getParameterName.ts b/packages/react-docgen/src/utils/getParameterName.ts deleted file mode 100644 index 5317301b6a2..00000000000 --- a/packages/react-docgen/src/utils/getParameterName.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { FunctionParameter, TSParameterProperty } from '@babel/types'; -import printValue from './printValue.js'; - -type ParameterNodePath = NodePath; - -export default function getParameterName( - parameterPath: ParameterNodePath, -): string { - if (parameterPath.isIdentifier()) { - return parameterPath.node.name; - } else if (parameterPath.isAssignmentPattern()) { - return getParameterName(parameterPath.get('left') as ParameterNodePath); - } else if ( - parameterPath.isObjectPattern() || - parameterPath.isArrayPattern() - ) { - return printValue(parameterPath); - } else if (parameterPath.isRestElement()) { - return `...${getParameterName( - parameterPath.get('argument') as ParameterNodePath, - )}`; - } else if (parameterPath.isTSParameterProperty()) { - return getParameterName(parameterPath.get('parameter')); - } else if (parameterPath.isVoidPattern()) { - return 'void'; - } - - throw new TypeError( - 'Parameter name must be one of Identifier, AssignmentPattern, ArrayPattern, ' + - `ObjectPattern, RestElement, or VoidPattern instead got ${parameterPath.node.type}`, - ); -} diff --git a/packages/react-docgen/src/utils/getPropType.ts b/packages/react-docgen/src/utils/getPropType.ts deleted file mode 100644 index 07b4ccfd0e6..00000000000 --- a/packages/react-docgen/src/utils/getPropType.ts +++ /dev/null @@ -1,338 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import { getDocblock } from '../utils/docblock.js'; -import getMembers from './getMembers.js'; -import getPropertyName from './getPropertyName.js'; -import isRequiredPropType from '../utils/isRequiredPropType.js'; -import printValue from './printValue.js'; -import resolveToValue from './resolveToValue.js'; -import resolveObjectKeysToArray from './resolveObjectKeysToArray.js'; -import resolveObjectValuesToArray from './resolveObjectValuesToArray.js'; -import type { PropTypeDescriptor } from '../Documentation.js'; -import type { ArrayExpression, Expression, SpreadElement } from '@babel/types'; - -function getEnumValuesFromArrayExpression( - path: NodePath, -): Array> { - const values: Array> = []; - - path.get('elements').forEach((elementPath) => { - if (!elementPath.hasNode()) return; - - if (elementPath.isSpreadElement()) { - const value = resolveToValue(elementPath.get('argument')); - - if (value.isArrayExpression()) { - // if the SpreadElement resolved to an Array, add all their elements too - return values.push(...getEnumValuesFromArrayExpression(value)); - } else { - // otherwise we'll just print the SpreadElement itself - return values.push({ - value: printValue(elementPath), - computed: !elementPath.isLiteral(), - }); - } - } - - // try to resolve the array element to it's value - const value = resolveToValue(elementPath as NodePath); - - return values.push({ - value: printValue( - value.parentPath?.isImportDeclaration() ? elementPath : value, - ), - computed: !value.isLiteral(), - }); - }); - - return values; -} - -function getPropTypeOneOf( - type: PropTypeDescriptor, - argumentPath: NodePath, -): PropTypeDescriptor { - const value = resolveToValue(argumentPath); - - if (value.isArrayExpression()) { - type.value = getEnumValuesFromArrayExpression(value); - } else { - const objectValues = - resolveObjectKeysToArray(value) || resolveObjectValuesToArray(value); - - if (objectValues) { - type.value = objectValues.map((objectValue) => ({ - value: objectValue, - computed: false, - })); - } else { - // could not easily resolve to an Array, let's print the original value - type.computed = true; - type.value = printValue(argumentPath); - } - } - - return type; -} - -function getPropTypeOneOfType( - type: PropTypeDescriptor, - argumentPath: NodePath, -): PropTypeDescriptor { - if (argumentPath.isArrayExpression()) { - type.value = argumentPath.get('elements').map((elementPath) => { - if (!elementPath.hasNode()) return; - const descriptor: PropTypeDescriptor = getPropType(elementPath); - const docs = getDocblock( - elementPath as NodePath, - ); - - if (docs) { - descriptor.description = docs; - } - - return descriptor; - }); - } - - return type; -} - -function getPropTypeArrayOf( - type: PropTypeDescriptor, - argumentPath: NodePath, -): PropTypeDescriptor { - const docs = getDocblock(argumentPath); - - if (docs) { - type.description = docs; - } - - const subType = getPropType(argumentPath); - - type.value = subType; - - return type; -} - -function getPropTypeObjectOf( - type: PropTypeDescriptor, - argumentPath: NodePath, -): PropTypeDescriptor { - const docs = getDocblock(argumentPath); - - if (docs) { - type.description = docs; - } - - const subType = getPropType(argumentPath); - - type.value = subType; - - return type; -} - -function getFirstArgument(path: NodePath): NodePath | undefined { - let argument: NodePath | undefined; - - if (path.isCallExpression()) { - argument = path.get('arguments')[0]; - } else { - const members = getMembers(path, true); - - if (members[0] && members[0].argumentPaths[0]) { - argument = members[0].argumentPaths[0]; - } - } - - return argument; -} - -function isCyclicReference( - argument: NodePath, - argumentPath: NodePath, -): boolean { - return Boolean(argument && resolveToValue(argument) === argumentPath); -} - -/** - * Handles shape and exact prop types - */ -function getPropTypeShapish( - type: PropTypeDescriptor, - argumentPath: NodePath, -): PropTypeDescriptor { - if (!argumentPath.isObjectExpression()) { - argumentPath = resolveToValue(argumentPath); - } - - if (argumentPath.isObjectExpression()) { - const value: Record = {}; - let rawValue: string | undefined; - - argumentPath.get('properties').forEach((propertyPath) => { - // We only handle ObjectProperty as there is nothing to handle for - // SpreadElements and ObjectMethods - if (propertyPath.isObjectProperty()) { - const propertyName = getPropertyName(propertyPath); - - if (!propertyName) return; - - const valuePath = propertyPath.get('value'); - const argument = getFirstArgument(valuePath); - - // This indicates we have a cyclic reference in the shape - // In this case we simply print the argument to shape and bail - if (argument && isCyclicReference(argument, argumentPath)) { - rawValue = printValue(argument); - - return; - } - - const descriptor = getPropType(valuePath); - const docs = getDocblock(propertyPath); - - if (docs) { - descriptor.description = docs; - } - descriptor.required = isRequiredPropType(valuePath); - value[propertyName] = descriptor; - } - }); - - type.value = rawValue ?? value; - } - - return type; -} - -function getPropTypeInstanceOf( - _type: PropTypeDescriptor, - argumentPath: NodePath, -): PropTypeDescriptor { - return { - name: 'instanceOf', - value: printValue(argumentPath), - }; -} - -const simplePropTypes = [ - 'array', - 'bool', - 'func', - 'number', - 'object', - 'string', - 'any', - 'element', - 'node', - 'symbol', - 'elementType', -] as const; - -function isSimplePropType( - name: string, -): name is (typeof simplePropTypes)[number] { - return simplePropTypes.includes(name as (typeof simplePropTypes)[number]); -} - -type PropTypeHandler = ( - type: PropTypeDescriptor, - argumentPath: NodePath, -) => PropTypeDescriptor; - -const propTypes = new Map< - string, - (argumentPath: NodePath | undefined) => PropTypeDescriptor ->([ - ['oneOf', callPropTypeHandler.bind(null, 'enum', getPropTypeOneOf)], - ['oneOfType', callPropTypeHandler.bind(null, 'union', getPropTypeOneOfType)], - [ - 'instanceOf', - callPropTypeHandler.bind(null, 'instanceOf', getPropTypeInstanceOf), - ], - ['arrayOf', callPropTypeHandler.bind(null, 'arrayOf', getPropTypeArrayOf)], - ['objectOf', callPropTypeHandler.bind(null, 'objectOf', getPropTypeObjectOf)], - ['shape', callPropTypeHandler.bind(null, 'shape', getPropTypeShapish)], - ['exact', callPropTypeHandler.bind(null, 'exact', getPropTypeShapish)], -]); - -function callPropTypeHandler( - name: PropTypeDescriptor['name'], - handler: PropTypeHandler, - argumentPath: NodePath | undefined, -): PropTypeDescriptor { - let type: PropTypeDescriptor = { name }; - - if (argumentPath) { - type = handler(type, argumentPath); - } - - if (!type.value) { - // If there is no argument then leave the value an empty string - type.value = argumentPath ? printValue(argumentPath) : ''; - type.computed = true; - } - - return type; -} - -/** - * Tries to identify the prop type by inspecting the path for known - * prop type names. This method doesn't check whether the found type is actually - * from React.PropTypes. It simply assumes that a match has the same meaning - * as the React.PropTypes one. - * - * If there is no match, "custom" is returned. - */ -export default function getPropType(path: NodePath): PropTypeDescriptor { - let descriptor: PropTypeDescriptor | null = null; - - getMembers(path, true).some((member) => { - const memberPath = member.path; - let name: string | null = null; - - if (memberPath.isStringLiteral()) { - name = memberPath.node.value; - } else if (memberPath.isIdentifier() && !member.computed) { - name = memberPath.node.name; - } - if (name) { - if (isSimplePropType(name)) { - descriptor = { name }; - - return true; - } - const propTypeHandler = propTypes.get(name); - - if (propTypeHandler) { - descriptor = propTypeHandler(member.argumentPaths[0]); - - return true; - } - } - - return; - }); - - if (descriptor) { - return descriptor; - } - - if (path.isIdentifier() && isSimplePropType(path.node.name)) { - return { name: path.node.name }; - } - - if (path.isCallExpression()) { - const callee = path.get('callee'); - - if (callee.isIdentifier()) { - const propTypeHandler = propTypes.get(callee.node.name); - - if (propTypeHandler) { - return propTypeHandler(path.get('arguments')[0]); - } - } - } - - return { name: 'custom', raw: printValue(path) }; -} diff --git a/packages/react-docgen/src/utils/getPropertyName.ts b/packages/react-docgen/src/utils/getPropertyName.ts deleted file mode 100644 index 72e27dc3144..00000000000 --- a/packages/react-docgen/src/utils/getPropertyName.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { - ClassMethod, - ClassProperty, - Expression, - ObjectMethod, - ObjectProperty, - ObjectTypeProperty, - ObjectTypeSpreadProperty, - SpreadElement, - TSMethodSignature, - TSPropertySignature, -} from '@babel/types'; -import getNameOrValue from './getNameOrValue.js'; -import resolveToValue from './resolveToValue.js'; - -export const COMPUTED_PREFIX = '@computed#'; - -/** - * In an ObjectExpression, the name of a property can either be an identifier - * or a literal (or dynamic, but we don't support those). This function simply - * returns the value of the literal or name of the identifier. - */ -export default function getPropertyName( - propertyPath: NodePath< - | ClassMethod - | ClassProperty - | ObjectMethod - | ObjectProperty - | ObjectTypeProperty - | ObjectTypeSpreadProperty - | SpreadElement - | TSMethodSignature - | TSPropertySignature - >, -): string | null { - if (propertyPath.isObjectTypeSpreadProperty()) { - const argument = propertyPath.get('argument'); - - if (argument.isGenericTypeAnnotation()) { - return getNameOrValue(argument.get('id')) as string; - } - - return null; - } else if (propertyPath.has('computed')) { - const key = propertyPath.get('key') as NodePath; - - // Try to resolve variables and member expressions - if (key.isIdentifier() || key.isMemberExpression()) { - const valuePath = resolveToValue(key); - - if (valuePath.isStringLiteral() || valuePath.isNumericLiteral()) { - return `${valuePath.node.value}`; - } - } - - // generate name for identifier - if (key.isIdentifier()) { - return `${COMPUTED_PREFIX}${key.node.name}`; - } - - if (key.isStringLiteral() || key.isNumericLiteral()) { - return `${key.node.value}`; - } - - return null; - } - - return `${getNameOrValue(propertyPath.get('key') as NodePath)}`; -} diff --git a/packages/react-docgen/src/utils/getPropertyValuePath.ts b/packages/react-docgen/src/utils/getPropertyValuePath.ts deleted file mode 100644 index d8e6fa03f1a..00000000000 --- a/packages/react-docgen/src/utils/getPropertyValuePath.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { Expression, ObjectExpression, ObjectMethod } from '@babel/types'; -import getPropertyName from './getPropertyName.js'; - -/** - * Given an ObjectExpression, this function returns the path of the value of - * the property with name `propertyName`. if the property is an ObjectMethod we - * return the ObjectMethod itself. - */ -export default function getPropertyValuePath( - path: NodePath, - propertyName: string, -): NodePath | null { - const property = path - .get('properties') - .find( - (propertyPath) => - !propertyPath.isSpreadElement() && - getPropertyName(propertyPath) === propertyName, - ); - - if (property) { - return property.isObjectMethod() - ? property - : (property.get('value') as NodePath); - } - - return null; -} diff --git a/packages/react-docgen/src/utils/getTSType.ts b/packages/react-docgen/src/utils/getTSType.ts deleted file mode 100644 index c938bf9470b..00000000000 --- a/packages/react-docgen/src/utils/getTSType.ts +++ /dev/null @@ -1,567 +0,0 @@ -import getPropertyName from './getPropertyName.js'; -import printValue from './printValue.js'; -import getTypeAnnotation from '../utils/getTypeAnnotation.js'; -import resolveToValue from '../utils/resolveToValue.js'; -import { resolveObjectToNameArray } from '../utils/resolveObjectKeysToArray.js'; -import type { TypeParameters } from '../utils/getTypeParameters.js'; -import getTypeParameters from '../utils/getTypeParameters.js'; -import type { - ElementsType, - FunctionArgumentType, - LiteralType, - ObjectSignatureType, - SimpleType, - TypeDescriptor, - TSFunctionSignatureType, -} from '../Documentation.js'; -import type { NodePath } from '@babel/traverse'; -import type { - TSUnionType, - TSFunctionType, - TSIntersectionType, - TSMappedType, - TSTupleType, - TSInterfaceDeclaration, - TSTypeLiteral, - TSTypeReference, - TSArrayType, - TSCallSignatureDeclaration, - TSIndexedAccessType, - TSTypeQuery, - TSType, - TSTypeAnnotation, - TSTypeOperator, - Identifier, - TSTypeParameterDeclaration, - TypeScript, - TSQualifiedName, - TSLiteralType, -} from '@babel/types'; -import { getDocblock } from './docblock.js'; - -const tsTypes: Record = { - TSAnyKeyword: 'any', - TSBooleanKeyword: 'boolean', - TSUnknownKeyword: 'unknown', - TSNeverKeyword: 'never', - TSNullKeyword: 'null', - TSUndefinedKeyword: 'undefined', - TSNumberKeyword: 'number', - TSStringKeyword: 'string', - TSSymbolKeyword: 'symbol', - TSThisType: 'this', - TSObjectKeyword: 'object', - TSVoidKeyword: 'void', -}; - -const namedTypes: Record< - string, - ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - path: NodePath, - typeParams: TypeParameters | null, - ) => TypeDescriptor | null -> = { - TSArrayType: handleTSArrayType, - TSTypeReference: handleTSTypeReference, - TSTypeLiteral: handleTSTypeLiteral, - TSInterfaceDeclaration: handleTSInterfaceDeclaration, - TSUnionType: handleTSUnionType, - TSFunctionType: handleTSFunctionType, - TSIntersectionType: handleTSIntersectionType, - TSMappedType: handleTSMappedType, - TSTupleType: handleTSTupleType, - TSTypeQuery: handleTSTypeQuery, - TSTypeOperator: handleTSTypeOperator, - TSIndexedAccessType: handleTSIndexedAccessType, - TSLiteralType: handleTSLiteralType, -}; - -function handleTSQualifiedName( - path: NodePath, -): TypeDescriptor { - const left = path.get('left'); - const right = path.get('right'); - - if (left.isIdentifier({ name: 'React' }) && right.isIdentifier()) { - return { - name: `${left.node.name}${right.node.name}`, - raw: printValue(path), - }; - } - - return { name: printValue(path).replace(/<.*>$/, '') }; -} - -function handleTSLiteralType(path: NodePath): LiteralType { - const literal = path.get('literal'); - - return { - name: 'literal', - value: printValue(literal), - }; -} - -function handleTSArrayType( - path: NodePath, - typeParams: TypeParameters | null, -): ElementsType { - return { - name: 'Array', - elements: [getTSTypeWithResolvedTypes(path.get('elementType'), typeParams)], - raw: printValue(path), - }; -} - -function handleTSTypeReference( - path: NodePath, - typeParams: TypeParameters | null, -): TypeDescriptor | null { - let type: TypeDescriptor; - const typeName = path.get('typeName'); - - if (typeName.isTSQualifiedName()) { - type = handleTSQualifiedName(typeName); - } else { - type = { name: (typeName as NodePath).node.name }; - } - - const resolvedPath = - (typeParams && typeParams[type.name]) || - resolveToValue(path.get('typeName')); - - const typeParameters = path.get('typeParameters'); - const resolvedTypeParameters = resolvedPath.get('typeParameters') as NodePath< - TSTypeParameterDeclaration | null | undefined - >; - - if (typeParameters.hasNode() && resolvedTypeParameters.hasNode()) { - typeParams = getTypeParameters( - resolvedTypeParameters, - typeParameters, - typeParams, - ); - } - - if (typeParams && typeParams[type.name]) { - // Open question: Why is this `null` instead of `typeParams` - type = getTSTypeWithResolvedTypes( - resolvedPath as NodePath, - null, - ); - } - - const resolvedTypeAnnotation = resolvedPath.get('typeAnnotation') as NodePath< - TSType | TSTypeAnnotation | null | undefined - >; - - if (resolvedTypeAnnotation.hasNode()) { - type = getTSTypeWithResolvedTypes(resolvedTypeAnnotation, typeParams); - } else if (typeParameters.hasNode()) { - const params = typeParameters.get('params'); - - type = { - ...(type as SimpleType), - elements: params.map((param) => - getTSTypeWithResolvedTypes(param, typeParams), - ), - raw: printValue(path), - }; - } - - return type; -} - -function getTSTypeWithRequirements( - path: NodePath, - typeParams: TypeParameters | null, -): TypeDescriptor { - const type = getTSTypeWithResolvedTypes(path, typeParams); - - type.required = - !('optional' in path.parentPath.node) || !path.parentPath.node.optional; - - return type; -} - -function handleTSTypeLiteral( - path: NodePath, - typeParams: TypeParameters | null, -): ObjectSignatureType { - const type: ObjectSignatureType = { - name: 'signature', - type: 'object', - raw: printValue(path), - signature: { properties: [] }, - }; - - path.get('members').forEach((param) => { - const typeAnnotation = param.get('typeAnnotation') as NodePath< - TSTypeAnnotation | null | undefined - >; - - if ( - (param.isTSPropertySignature() || param.isTSMethodSignature()) && - typeAnnotation.hasNode() - ) { - const propName = getPropertyName(param); - - if (!propName) { - return; - } - const docblock = getDocblock(param); - let doc = {}; - - if (docblock) { - doc = { description: docblock }; - } - - type.signature.properties.push({ - key: propName, - value: getTSTypeWithRequirements(typeAnnotation, typeParams), - ...doc, - }); - } else if (param.isTSCallSignatureDeclaration()) { - type.signature.constructor = handleTSFunctionType(param, typeParams); - } else if (param.isTSIndexSignature() && typeAnnotation.hasNode()) { - const parameters = param.get('parameters'); - - if (parameters[0]) { - const idTypeAnnotation = parameters[0].get( - 'typeAnnotation', - ) as NodePath; - - if (idTypeAnnotation.hasNode()) { - type.signature.properties.push({ - key: getTSTypeWithResolvedTypes(idTypeAnnotation, typeParams), - value: getTSTypeWithRequirements(typeAnnotation, typeParams), - }); - } - } - } - }); - - return type; -} - -function handleTSInterfaceDeclaration( - path: NodePath, -): SimpleType { - // Interfaces are handled like references which would be documented separately, - // rather than inlined like type aliases. - return { - name: path.node.id.name, - }; -} - -function handleTSUnionType( - path: NodePath, - typeParams: TypeParameters | null, -): ElementsType { - return { - name: 'union', - raw: printValue(path), - elements: path - .get('types') - .map((subType) => getTSTypeWithResolvedTypes(subType, typeParams)), - }; -} - -function handleTSIntersectionType( - path: NodePath, - typeParams: TypeParameters | null, -): ElementsType { - return { - name: 'intersection', - raw: printValue(path), - elements: path - .get('types') - .map((subType) => getTSTypeWithResolvedTypes(subType, typeParams)), - }; -} - -// type OptionsFlags = { [Property in keyof Type]; }; -function handleTSMappedType( - path: NodePath, - typeParams: TypeParameters | null, -): ObjectSignatureType { - const key = getTSTypeWithResolvedTypes( - path.get('typeParameter').get('constraint') as NodePath, - typeParams, - ); - - key.required = !path.node.optional; - - const typeAnnotation = path.get('typeAnnotation'); - let value: TypeDescriptor; - - if (typeAnnotation.hasNode()) { - value = getTSTypeWithResolvedTypes(typeAnnotation, typeParams); - } else { - value = { name: 'any' }; - } - - return { - name: 'signature', - type: 'object', - raw: printValue(path), - signature: { - properties: [ - { - key, - value, - }, - ], - }, - }; -} - -function handleTSFunctionType( - path: NodePath, - typeParams: TypeParameters | null, -): TSFunctionSignatureType { - let returnType: TypeDescriptor | undefined; - - const annotation = path.get('typeAnnotation'); - - if (annotation.hasNode()) { - returnType = getTSTypeWithResolvedTypes(annotation, typeParams); - } - - const type: TSFunctionSignatureType = { - name: 'signature', - type: 'function', - raw: printValue(path), - signature: { - arguments: [], - return: returnType, - }, - }; - - path.get('parameters').forEach((param) => { - const typeAnnotation = getTypeAnnotation(param); - - const arg: FunctionArgumentType = { - type: typeAnnotation - ? getTSTypeWithResolvedTypes(typeAnnotation, typeParams) - : undefined, - name: '', - }; - - if (param.isIdentifier()) { - arg.name = param.node.name; - - if (param.node.name === 'this') { - type.signature.this = arg.type; - - return; - } - } else if (param.isRestElement()) { - const restArgument = param.get('argument'); - - if (restArgument.isIdentifier()) { - arg.name = restArgument.node.name; - } else { - arg.name = printValue(restArgument); - } - arg.rest = true; - } - - type.signature.arguments.push(arg); - }); - - return type; -} - -function handleTSTupleType( - path: NodePath, - typeParams: TypeParameters | null, -): ElementsType { - const type: ElementsType = { - name: 'tuple', - raw: printValue(path), - elements: [], - }; - - path.get('elementTypes').forEach((param) => { - type.elements.push(getTSTypeWithResolvedTypes(param, typeParams)); - }); - - return type; -} - -function handleTSTypeQuery( - path: NodePath, - typeParams: TypeParameters | null, -): TypeDescriptor { - const exprName = path.get('exprName'); - - if (exprName.isIdentifier()) { - const resolvedPath = resolveToValue(path.get('exprName')); - - if (resolvedPath.has('typeAnnotation')) { - return getTSTypeWithResolvedTypes( - resolvedPath.get('typeAnnotation') as NodePath, - typeParams, - ); - } - - return { name: exprName.node.name }; - } else if (exprName.isTSQualifiedName()) { - return handleTSQualifiedName(exprName); - } else { - // TSImportType - return { name: printValue(exprName) }; - } -} - -function handleTSTypeOperator( - path: NodePath, - typeParams: TypeParameters | null, -): TypeDescriptor | null { - if (path.node.operator !== 'keyof') { - return null; - } - - let value: NodePath = path.get('typeAnnotation'); - - if (value.isTSTypeQuery()) { - value = value.get('exprName'); - } else if ('id' in value.node) { - value = value.get('id') as NodePath; - } else if (value.isTSTypeReference()) { - return getTSTypeWithResolvedTypes(value, typeParams); - } - - const resolvedPath = resolveToValue(value); - - if (resolvedPath.isObjectExpression() || resolvedPath.isTSTypeLiteral()) { - const keys = resolveObjectToNameArray(resolvedPath, true); - - if (keys) { - return { - name: 'union', - raw: printValue(path), - elements: keys.map((key) => ({ name: 'literal', value: key })), - }; - } - } - - return null; -} - -function handleTSIndexedAccessType( - path: NodePath, - typeParams: TypeParameters | null, -): SimpleType { - const objectType = getTSTypeWithResolvedTypes( - path.get('objectType'), - typeParams, - ) as ObjectSignatureType; - const indexType = getTSTypeWithResolvedTypes( - path.get('indexType'), - typeParams, - ) as LiteralType; - - // We only get the signature if the objectType is a type (vs interface) - if (!objectType.signature) { - return { - name: `${objectType.name}[${ - indexType.value ? indexType.value.toString() : indexType.name - }]`, - raw: printValue(path), - }; - } - - const resolvedType = objectType.signature.properties.find((p) => { - // indexType.value = "'foo'" - return indexType.value && p.key === indexType.value.replace(/['"]+/g, ''); - }); - - if (!resolvedType) { - return { name: 'unknown' }; - } - - return { - name: resolvedType.value.name, - raw: printValue(path), - }; -} - -let visitedTypes: Record< - string, - TypeDescriptor | true -> = {}; - -function getTSTypeWithResolvedTypes( - path: NodePath, - typeParams: TypeParameters | null, -): TypeDescriptor { - if (path.isTSTypeAnnotation()) { - path = path.get('typeAnnotation'); - } - - const node = path.node; - let type: TypeDescriptor | null = null; - let typeAliasName: string | null = null; - - if (path.parentPath.isTSTypeAliasDeclaration()) { - typeAliasName = path.parentPath.node.id.name; - } - - // When we see a typealias mark it as visited so that the next - // call of this function does not run into an endless loop - if (typeAliasName) { - if (visitedTypes[typeAliasName] === true) { - // if we are currently visiting this node then just return the name - // as we are starting to endless loop - return { name: typeAliasName }; - } else if (typeof visitedTypes[typeAliasName] === 'object') { - // if we already resolved the type simple return it - return visitedTypes[ - typeAliasName - ] as TypeDescriptor; - } - // mark the type as visited - visitedTypes[typeAliasName] = true; - } - - if (node.type in tsTypes) { - type = { name: tsTypes[node.type]! }; - } else if (node.type in namedTypes) { - type = namedTypes[node.type]!(path, typeParams); - } - - if (!type) { - type = { name: 'unknown' }; - } - - if (typeAliasName) { - // mark the type as unvisited so that further calls can resolve the type again - visitedTypes[typeAliasName] = type; - } - - return type; -} - -/** - * Tries to identify the typescript type by inspecting the path for known - * typescript type names. This method doesn't check whether the found type is actually - * existing. It simply assumes that a match is always valid. - * - * If there is no match, "unknown" is returned. - */ -export default function getTSType( - path: NodePath, - typeParamMap: TypeParameters | null = null, -): TypeDescriptor { - // Empty visited types before an after run - // Before: in case the detection threw and we rerun again - // After: cleanup memory after we are done here - visitedTypes = {}; - const type = getTSTypeWithResolvedTypes(path, typeParamMap); - - visitedTypes = {}; - - return type; -} diff --git a/packages/react-docgen/src/utils/getTypeAnnotation.ts b/packages/react-docgen/src/utils/getTypeAnnotation.ts deleted file mode 100644 index 3424700b150..00000000000 --- a/packages/react-docgen/src/utils/getTypeAnnotation.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { FlowType, Node, TSType } from '@babel/types'; - -/** - * Gets the most inner valuable TypeAnnotation from path. If no TypeAnnotation - * can be found null is returned - */ -export default function getTypeAnnotation( - path: NodePath, -): NodePath | null { - if (!path.has('typeAnnotation')) return null; - - let resultPath = path; - - do { - resultPath = resultPath.get('typeAnnotation') as NodePath; - } while ( - resultPath.has('typeAnnotation') && - !resultPath.isFlowType() && - !resultPath.isTSType() - ); - - return resultPath as NodePath; -} diff --git a/packages/react-docgen/src/utils/getTypeFromReactComponent.ts b/packages/react-docgen/src/utils/getTypeFromReactComponent.ts deleted file mode 100644 index 1e0752a8b8f..00000000000 --- a/packages/react-docgen/src/utils/getTypeFromReactComponent.ts +++ /dev/null @@ -1,245 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type Documentation from '../Documentation.js'; -import getMemberValuePath from './getMemberValuePath.js'; -import getTypeAnnotation from './getTypeAnnotation.js'; -import getTypeParameters from './getTypeParameters.js'; -import isReactComponentClass from './isReactComponentClass.js'; -import isReactForwardRefCall from './isReactForwardRefCall.js'; -import resolveGenericTypeAnnotation from './resolveGenericTypeAnnotation.js'; -import resolveToValue from './resolveToValue.js'; -import type { TypeParameters } from './getTypeParameters.js'; -import type { - FlowType, - InterfaceDeclaration, - InterfaceExtends, - TSExpressionWithTypeArguments, - TSInterfaceDeclaration, - TSType, - TSTypeParameterDeclaration, - TSTypeParameterInstantiation, - TypeParameterDeclaration, - TypeParameterInstantiation, - VariableDeclarator, -} from '@babel/types'; -import getTypeIdentifier from './getTypeIdentifier.js'; -import isReactBuiltinReference from './isReactBuiltinReference.js'; -import unwrapBuiltinTSPropTypes from './unwrapBuiltinTSPropTypes.js'; - -function getStatelessPropsPath( - componentDefinition: NodePath, -): NodePath | undefined { - if (!componentDefinition.isFunction()) return; - - return componentDefinition.get('params')[0]; -} - -function getForwardRefGenericsType( - componentDefinition: NodePath, -): NodePath | null { - const typeParameters = componentDefinition.get('typeParameters') as NodePath< - TSTypeParameterInstantiation | null | undefined - >; - - if (typeParameters && typeParameters.hasNode()) { - const params = typeParameters.get('params'); - - return params[1] ?? null; - } - - return null; -} - -function findAssignedVariableType( - componentDefinition: NodePath, -): NodePath | null { - const variableDeclarator = componentDefinition.findParent((path) => - path.isVariableDeclarator(), - ) as NodePath | null; - - if (!variableDeclarator) return null; - - const typeAnnotation = getTypeAnnotation(variableDeclarator.get('id')); - - if (!typeAnnotation) return null; - - if (typeAnnotation.isTSTypeReference()) { - const typeName = typeAnnotation.get('typeName'); - - if ( - isReactBuiltinReference(typeName, 'FunctionComponent') || - isReactBuiltinReference(typeName, 'FC') || - isReactBuiltinReference(typeName, 'VoidFunctionComponent') || - isReactBuiltinReference(typeName, 'VFC') - ) { - const typeParameters = typeAnnotation.get('typeParameters'); - - if (typeParameters.hasNode()) { - return typeParameters.get('params')[0] ?? null; - } - } - } - - return null; -} - -/** - * Given an React component (stateless or class) tries to find - * flow or TS types for the props. It may find multiple types. - * If not found or it is not one of the supported component types, - * this function returns an empty array. - */ -export default (componentDefinition: NodePath): NodePath[] => { - const typePaths: NodePath[] = []; - - if (isReactComponentClass(componentDefinition)) { - const superTypes = componentDefinition.get('superTypeParameters'); - - if (superTypes.hasNode()) { - const params = superTypes.get('params'); - - if (params.length >= 1) { - typePaths.push(params[params.length === 3 ? 1 : 0]!); - } - } else { - const propsMemberPath = getMemberValuePath(componentDefinition, 'props'); - - if (!propsMemberPath) { - return []; - } - - const typeAnnotation = getTypeAnnotation(propsMemberPath.parentPath); - - if (typeAnnotation) { - typePaths.push(typeAnnotation); - } - } - } else { - if (isReactForwardRefCall(componentDefinition)) { - const genericTypeAnnotation = - getForwardRefGenericsType(componentDefinition); - - if (genericTypeAnnotation) { - typePaths.push(genericTypeAnnotation); - } - - componentDefinition = resolveToValue( - componentDefinition.get('arguments')[0]!, - ); - } - - const propsParam = getStatelessPropsPath(componentDefinition); - - if (propsParam) { - const typeAnnotation = getTypeAnnotation(propsParam); - - if (typeAnnotation) { - typePaths.push(typeAnnotation); - } - } - - const assignedVariableType = findAssignedVariableType(componentDefinition); - - if (assignedVariableType) { - typePaths.push(assignedVariableType); - } - } - - return typePaths.map((typePath) => unwrapBuiltinTSPropTypes(typePath)); -}; - -export function applyToTypeProperties( - documentation: Documentation, - path: NodePath, - callback: (propertyPath: NodePath, params: TypeParameters | null) => void, - typeParams: TypeParameters | null, -): void { - if (path.isObjectTypeAnnotation()) { - path - .get('properties') - .forEach((propertyPath) => callback(propertyPath, typeParams)); - } else if (path.isTSTypeLiteral()) { - path - .get('members') - .forEach((propertyPath) => callback(propertyPath, typeParams)); - } else if (path.isInterfaceDeclaration()) { - applyExtends(documentation, path, callback, typeParams); - - path - .get('body') - .get('properties') - .forEach((propertyPath) => callback(propertyPath, typeParams)); - } else if (path.isTSInterfaceDeclaration()) { - applyExtends(documentation, path, callback, typeParams); - - path - .get('body') - .get('body') - .forEach((propertyPath) => callback(propertyPath, typeParams)); - } else if ( - path.isIntersectionTypeAnnotation() || - path.isTSIntersectionType() - ) { - (path.get('types') as Array>).forEach( - (typesPath) => - applyToTypeProperties(documentation, typesPath, callback, typeParams), - ); - } else if (!path.isUnionTypeAnnotation()) { - // The react-docgen output format does not currently allow - // for the expression of union types - const typePath = resolveGenericTypeAnnotation(path); - - if (typePath) { - applyToTypeProperties(documentation, typePath, callback, typeParams); - } - } -} - -function applyExtends( - documentation: Documentation, - path: NodePath, - callback: (propertyPath: NodePath, params: TypeParameters | null) => void, - typeParams: TypeParameters | null, -): void { - const classExtends = path.get('extends'); - - if (!Array.isArray(classExtends)) { - return; - } - - classExtends.forEach( - ( - extendsPath: NodePath, - ) => { - const resolvedPath = resolveGenericTypeAnnotation(extendsPath); - - if (resolvedPath) { - if ( - resolvedPath.has('typeParameters') && - extendsPath.node.typeParameters - ) { - typeParams = getTypeParameters( - resolvedPath.get('typeParameters') as NodePath< - TSTypeParameterDeclaration | TypeParameterDeclaration - >, - extendsPath.get('typeParameters') as NodePath< - TSTypeParameterInstantiation | TypeParameterInstantiation - >, - typeParams, - ); - } - applyToTypeProperties( - documentation, - resolvedPath, - callback, - typeParams, - ); - } else { - const idPath = getTypeIdentifier(extendsPath); - - if (idPath && idPath.isIdentifier()) { - documentation.addComposes(idPath.node.name); - } - } - }, - ); -} diff --git a/packages/react-docgen/src/utils/getTypeIdentifier.ts b/packages/react-docgen/src/utils/getTypeIdentifier.ts deleted file mode 100644 index 99e3f1c154f..00000000000 --- a/packages/react-docgen/src/utils/getTypeIdentifier.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { NodePath } from '@babel/traverse'; - -export default function getTypeIdentifier(path: NodePath): NodePath | null { - if (path.has('id')) { - return path.get('id') as NodePath; - } else if (path.isTSTypeReference()) { - return path.get('typeName'); - } else if (path.isTSExpressionWithTypeArguments()) { - return path.get('expression'); - } - - return null; -} diff --git a/packages/react-docgen/src/utils/getTypeParameters.ts b/packages/react-docgen/src/utils/getTypeParameters.ts deleted file mode 100644 index 5ce7f016178..00000000000 --- a/packages/react-docgen/src/utils/getTypeParameters.ts +++ /dev/null @@ -1,67 +0,0 @@ -import resolveGenericTypeAnnotation from '../utils/resolveGenericTypeAnnotation.js'; -import type { NodePath } from '@babel/traverse'; -import type { - Identifier, - QualifiedTypeIdentifier, - TSQualifiedName, - TSTypeParameter, - TSTypeParameterDeclaration, - TSTypeParameterInstantiation, - TypeParameter, - TypeParameterDeclaration, - TypeParameterInstantiation, -} from '@babel/types'; - -export type TypeParameters = Record; - -export default function getTypeParameters( - declaration: NodePath, - instantiation: NodePath< - TSTypeParameterInstantiation | TypeParameterInstantiation - >, - inputParams: TypeParameters | null | undefined, -): TypeParameters { - const params: TypeParameters = {}; - const numInstantiationParams = instantiation.node.params.length; - - let i = 0; - - declaration - .get('params') - .forEach((paramPath: NodePath) => { - const key = paramPath.node.name; - const defaultProp = paramPath.get('default'); - const defaultTypePath = defaultProp.hasNode() ? defaultProp : null; - const typePath = - i < numInstantiationParams - ? instantiation.get('params')[i++] - : defaultTypePath; - - if (typePath) { - let resolvedTypePath: NodePath = - resolveGenericTypeAnnotation(typePath) || typePath; - let typeName: - | NodePath - | undefined; - - if (resolvedTypePath.isTSTypeReference()) { - typeName = resolvedTypePath.get('typeName'); - } else if (resolvedTypePath.isGenericTypeAnnotation()) { - typeName = resolvedTypePath.get('id'); - } - - if ( - typeName && - inputParams && - typeName.isIdentifier() && - inputParams[typeName.node.name] - ) { - resolvedTypePath = inputParams[typeName.node.name]!; - } - - params[key] = resolvedTypePath; - } - }); - - return params; -} diff --git a/packages/react-docgen/src/utils/index.ts b/packages/react-docgen/src/utils/index.ts deleted file mode 100644 index dc3a1968003..00000000000 --- a/packages/react-docgen/src/utils/index.ts +++ /dev/null @@ -1,69 +0,0 @@ -import * as docblock from './docblock.js'; -import * as expressionTo from './expressionTo.js'; -import * as flowUtilityTypes from './flowUtilityTypes.js'; -import * as traverse from './traverse.js'; - -export { docblock, expressionTo, flowUtilityTypes, traverse }; - -export { default as findFunctionReturn } from './findFunctionReturn.js'; -export { default as getClassMemberValuePath } from './getClassMemberValuePath.js'; -export { default as getFlowType } from './getFlowType.js'; -export { default as getMemberExpressionRoot } from './getMemberExpressionRoot.js'; -export { default as getMemberExpressionValuePath } from './getMemberExpressionValuePath.js'; -export { default as getMembers } from './getMembers.js'; -export { - default as getMemberValuePath, - isSupportedDefinitionType, -} from './getMemberValuePath.js'; -export { default as getMethodDocumentation } from './getMethodDocumentation.js'; -export type { MethodNodePath } from './getMethodDocumentation.js'; -export { default as getNameOrValue } from './getNameOrValue.js'; -export { default as getParameterName } from './getParameterName.js'; -export { - default as getPropertyName, - COMPUTED_PREFIX, -} from './getPropertyName.js'; -export { default as getPropertyValuePath } from './getPropertyValuePath.js'; -export { default as getPropType } from './getPropType.js'; -export { default as getTSType } from './getTSType.js'; -export { default as getTypeAnnotation } from './getTypeAnnotation.js'; -export { - default as getTypeFromReactComponent, - applyToTypeProperties, -} from './getTypeFromReactComponent.js'; -export { default as getTypeIdentifier } from './getTypeIdentifier.js'; -export { default as getTypeParameters } from './getTypeParameters.js'; -export type { TypeParameters } from './getTypeParameters.js'; -export { default as isDestructuringAssignment } from './isDestructuringAssignment.js'; -export { default as isExportsOrModuleAssignment } from './isExportsOrModuleAssignment.js'; -export { default as isImportSpecifier } from './isImportSpecifier.js'; -export { default as isReactBuiltinCall } from './isReactBuiltinCall.js'; -export { default as isReactBuiltinReference } from './isReactBuiltinReference.js'; -export { default as isReactChildrenElementCall } from './isReactChildrenElementCall.js'; -export { default as isReactCloneElementCall } from './isReactCloneElementCall.js'; -export { default as isReactComponentClass } from './isReactComponentClass.js'; -export { default as isReactComponentMethod } from './isReactComponentMethod.js'; -export { default as isReactCreateClassCall } from './isReactCreateClassCall.js'; -export { default as isReactCreateElementCall } from './isReactCreateElementCall.js'; -export { default as isReactForwardRefCall } from './isReactForwardRefCall.js'; -export { default as isReactModuleName } from './isReactModuleName.js'; -export { default as isRequiredPropType } from './isRequiredPropType.js'; -export { default as isStatelessComponent } from './isStatelessComponent.js'; -export { default as isUnreachableFlowType } from './isUnreachableFlowType.js'; -export { default as normalizeClassDefinition } from './normalizeClassDefinition.js'; -export { default as parseJsDoc } from './parseJsDoc.js'; -export { default as postProcessDocumentation } from './postProcessDocumentation.js'; -export { default as printValue } from './printValue.js'; -export { default as resolveExportDeclaration } from './resolveExportDeclaration.js'; -export { default as resolveFunctionDefinitionToReturnValue } from './resolveFunctionDefinitionToReturnValue.js'; -export { default as resolveGenericTypeAnnotation } from './resolveGenericTypeAnnotation.js'; -export { default as resolveHOC } from './resolveHOC.js'; -export { default as resolveObjectPatternPropertyToValue } from './resolveObjectPatternPropertyToValue.js'; -export { - default as resolveObjectKeysToArray, - resolveObjectToNameArray, -} from './resolveObjectKeysToArray.js'; -export { default as resolveObjectValuesToArray } from './resolveObjectValuesToArray.js'; -export { default as resolveToModule } from './resolveToModule.js'; -export { default as resolveToValue } from './resolveToValue.js'; -export { default as setPropDescription } from './setPropDescription.js'; diff --git a/packages/react-docgen/src/utils/isDestructuringAssignment.ts b/packages/react-docgen/src/utils/isDestructuringAssignment.ts deleted file mode 100644 index 7c8f2581a35..00000000000 --- a/packages/react-docgen/src/utils/isDestructuringAssignment.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { NodePath } from '@babel/traverse'; - -/** - * Checks if the input Identifier is part of a destructuring Assignment - * and the name of the property key matches the input name - */ -export default function isDestructuringAssignment( - path: NodePath, - name: string, -): boolean { - if (!path.isObjectProperty()) { - return false; - } - - const id = path.get('key'); - - return id.isIdentifier({ name }) && path.parentPath.isObjectPattern(); -} diff --git a/packages/react-docgen/src/utils/isExportsOrModuleAssignment.ts b/packages/react-docgen/src/utils/isExportsOrModuleAssignment.ts deleted file mode 100644 index 656f414463f..00000000000 --- a/packages/react-docgen/src/utils/isExportsOrModuleAssignment.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import * as expressionTo from './expressionTo.js'; - -/** - * Returns true if the expression is of form `exports.foo = ...;` or - * `modules.exports = ...;`. - */ -export default function isExportsOrModuleAssignment(path: NodePath): boolean { - if ( - !path.isAssignmentExpression() || - !path.get('left').isMemberExpression() - ) { - return false; - } - - const exprArr = expressionTo.Array(path.get('left')); - - return ( - (exprArr[0] === 'module' && exprArr[1] === 'exports') || - exprArr[0] === 'exports' - ); -} diff --git a/packages/react-docgen/src/utils/isImportSpecifier.ts b/packages/react-docgen/src/utils/isImportSpecifier.ts deleted file mode 100644 index f6c86f00927..00000000000 --- a/packages/react-docgen/src/utils/isImportSpecifier.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { NodePath } from '@babel/traverse'; - -/** - * Checks if the path is a ImportSpecifier that imports the given named export - */ -export default function isImportSpecifier( - path: NodePath, - name: string, -): boolean { - return ( - path.isImportSpecifier() && - (path.get('imported').isIdentifier({ name }) || - path.get('imported').isStringLiteral({ value: name })) - ); -} diff --git a/packages/react-docgen/src/utils/isReactBuiltinCall.ts b/packages/react-docgen/src/utils/isReactBuiltinCall.ts deleted file mode 100644 index d6e92cce7e6..00000000000 --- a/packages/react-docgen/src/utils/isReactBuiltinCall.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { CallExpression } from '@babel/types'; -import isReactBuiltinReference from './isReactBuiltinReference.js'; - -/** - * Returns true if the expression is a function call of the form - * `React.foo(...)`. - */ -export default function isReactBuiltinCall( - path: NodePath, - name: string, -): path is NodePath { - if (!path.isCallExpression()) { - return false; - } - - const callee = path.get('callee'); - - return isReactBuiltinReference(callee, name); -} diff --git a/packages/react-docgen/src/utils/isReactBuiltinReference.ts b/packages/react-docgen/src/utils/isReactBuiltinReference.ts deleted file mode 100644 index 04ec26d59d0..00000000000 --- a/packages/react-docgen/src/utils/isReactBuiltinReference.ts +++ /dev/null @@ -1,71 +0,0 @@ -import isReactModuleName from './isReactModuleName.js'; -import resolveToModule from './resolveToModule.js'; -import resolveToValue from './resolveToValue.js'; -import isDestructuringAssignment from './isDestructuringAssignment.js'; -import type { NodePath } from '@babel/traverse'; -import isImportSpecifier from './isImportSpecifier.js'; - -function isNamedMemberExpression(value: NodePath, name: string): boolean { - if (!value.isMemberExpression()) { - return false; - } - - const property = value.get('property'); - - return property.isIdentifier() && property.node.name === name; -} - -/** - * Returns true if the expression is a reference to a react export. - */ -export default function isReactBuiltinReference( - path: NodePath, - name: string, -): boolean { - if ( - path.isMemberExpression() && - path.get('property').isIdentifier({ name }) - ) { - const module = resolveToModule(path.get('object')); - - return Boolean(module && isReactModuleName(module)); - } - - // Typescript - if (path.isTSQualifiedName() && path.get('right').isIdentifier({ name })) { - const module = resolveToModule(path.get('left')); - - return Boolean(module && isReactModuleName(module)); - } - - // Flow - if ( - path.isQualifiedTypeIdentifier() && - path.get('id').isIdentifier({ name }) - ) { - const module = resolveToModule(path.get('qualification')); - - return Boolean(module && isReactModuleName(module)); - } - - const value = resolveToValue(path); - - if (value === path) { - return false; - } - - if ( - // const { x } = require('react') - isDestructuringAssignment(value, name) || - // `require('react').createElement` - isNamedMemberExpression(value, name) || - // `import { createElement } from 'react'` - isImportSpecifier(value, name) - ) { - const module = resolveToModule(value); - - return Boolean(module && isReactModuleName(module)); - } - - return false; -} diff --git a/packages/react-docgen/src/utils/isReactChildrenElementCall.ts b/packages/react-docgen/src/utils/isReactChildrenElementCall.ts deleted file mode 100644 index 543ed9e246c..00000000000 --- a/packages/react-docgen/src/utils/isReactChildrenElementCall.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { CallExpression } from '@babel/types'; -import isReactBuiltinReference from './isReactBuiltinReference.js'; - -/** - * Returns true if the expression is a function call of the form - * `React.Children.only(...)` or `React.Children.map(...)`. - */ -export default function isReactChildrenElementCall( - path: NodePath, -): path is NodePath { - if (!path.isCallExpression()) { - return false; - } - - const callee = path.get('callee'); - - if (callee.isMemberExpression()) { - const calleeProperty = callee.get('property'); - - if ( - calleeProperty.isIdentifier({ name: 'only' }) || - calleeProperty.isIdentifier({ name: 'map' }) - ) { - return isReactBuiltinReference(callee.get('object'), 'Children'); - } - } - - return false; -} diff --git a/packages/react-docgen/src/utils/isReactCloneElementCall.ts b/packages/react-docgen/src/utils/isReactCloneElementCall.ts deleted file mode 100644 index 23db3e35ee0..00000000000 --- a/packages/react-docgen/src/utils/isReactCloneElementCall.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { CallExpression } from '@babel/types'; -import isReactBuiltinCall from './isReactBuiltinCall.js'; - -/** - * Returns true if the expression is a function call of the form - * `React.cloneElement(...)`. - */ -export default function isReactCloneElementCall( - path: NodePath, -): path is NodePath { - return isReactBuiltinCall(path, 'cloneElement'); -} diff --git a/packages/react-docgen/src/utils/isReactComponentClass.ts b/packages/react-docgen/src/utils/isReactComponentClass.ts deleted file mode 100644 index 114e2fc66b1..00000000000 --- a/packages/react-docgen/src/utils/isReactComponentClass.ts +++ /dev/null @@ -1,94 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { - ClassDeclaration, - ClassExpression, - ClassMethod, -} from '@babel/types'; -import isReactModuleName from './isReactModuleName.js'; -import resolveToModule from './resolveToModule.js'; -import resolveToValue from './resolveToValue.js'; -import isDestructuringAssignment from './isDestructuringAssignment.js'; -import isImportSpecifier from './isImportSpecifier.js'; - -function isRenderMethod(path: NodePath): boolean { - if ( - (!path.isClassMethod() || path.node.kind !== 'method') && - !path.isClassProperty() - ) { - return false; - } - - if (path.node.computed || path.node.static) { - return false; - } - - const key = path.get('key') as NodePath; - - if (!key.isIdentifier() || key.node.name !== 'render') { - return false; - } - - return true; -} - -function classExtendsReactComponent(path: NodePath): boolean { - if (path.isMemberExpression()) { - const property = path.get('property'); - - if ( - property.isIdentifier({ name: 'Component' }) || - property.isIdentifier({ name: 'PureComponent' }) - ) { - return true; - } - } else if ( - isImportSpecifier(path, 'Component') || - isImportSpecifier(path, 'PureComponent') - ) { - return true; - } else if ( - isDestructuringAssignment(path, 'Component') || - isDestructuringAssignment(path, 'PureComponent') - ) { - return true; - } - - return false; -} - -/** - * Returns `true` of the path represents a class definition which either extends - * `React.Component` or has a superclass and implements a `render()` method. - */ -export default function isReactComponentClass( - path: NodePath, -): path is NodePath { - if (!path.isClass()) { - return false; - } - - // React.Component or React.PureComponent - const superClass = path.get('superClass'); - - if (superClass.hasNode()) { - const resolvedSuperClass = resolveToValue(superClass); - - if (classExtendsReactComponent(resolvedSuperClass)) { - const module = resolveToModule(resolvedSuperClass); - - if (module && isReactModuleName(module)) { - return true; - } - } - } else { - // does not extend anything - return false; - } - - // render method - if (path.get('body').get('body').some(isRenderMethod)) { - return true; - } - - return false; -} diff --git a/packages/react-docgen/src/utils/isReactComponentMethod.ts b/packages/react-docgen/src/utils/isReactComponentMethod.ts deleted file mode 100644 index 9756544fdda..00000000000 --- a/packages/react-docgen/src/utils/isReactComponentMethod.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import getPropertyName from './getPropertyName.js'; - -const componentMethods = [ - 'componentDidMount', - 'componentDidReceiveProps', - 'componentDidUpdate', - 'componentWillMount', - 'UNSAFE_componentWillMount', - 'componentWillReceiveProps', - 'UNSAFE_componentWillReceiveProps', - 'componentWillUnmount', - 'componentWillUpdate', - 'UNSAFE_componentWillUpdate', - 'getChildContext', - 'getDefaultProps', - 'getInitialState', - 'render', - 'shouldComponentUpdate', - 'getDerivedStateFromProps', - 'getDerivedStateFromError', - 'getSnapshotBeforeUpdate', - 'componentDidCatch', -]; - -/** - * Returns if the method path is a Component method. - */ -export default function (methodPath: NodePath): boolean { - if ( - !methodPath.isClassMethod() && - !methodPath.isObjectMethod() && - !methodPath.isObjectProperty() - ) { - return false; - } - - const name = getPropertyName(methodPath); - - return Boolean(name && componentMethods.indexOf(name) !== -1); -} diff --git a/packages/react-docgen/src/utils/isReactCreateClassCall.ts b/packages/react-docgen/src/utils/isReactCreateClassCall.ts deleted file mode 100644 index 21b6d4f7f58..00000000000 --- a/packages/react-docgen/src/utils/isReactCreateClassCall.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import resolveToModule from './resolveToModule.js'; -import isReactBuiltinCall from './isReactBuiltinCall.js'; -import type { CallExpression } from '@babel/types'; - -/** - * Returns true if the expression is a function call of the form - * ``` - * import createReactClass from 'create-react-class'; - * createReactClass(...); - * ``` - */ -function isReactCreateClassCallModular(path: NodePath): boolean { - if (!path.isCallExpression()) { - return false; - } - const module = resolveToModule(path); - - return Boolean(module && module === 'create-react-class'); -} - -/** - * Returns true if the expression is a function call of the form - * `React.createClass(...)` or - * ``` - * import createReactClass from 'create-react-class'; - * createReactClass(...); - * ``` - */ -export default function isReactCreateClassCall( - path: NodePath, -): path is NodePath { - return ( - (isReactBuiltinCall(path, 'createClass') && - path.get('arguments').length === 1) || - isReactCreateClassCallModular(path) - ); -} diff --git a/packages/react-docgen/src/utils/isReactCreateElementCall.ts b/packages/react-docgen/src/utils/isReactCreateElementCall.ts deleted file mode 100644 index 5638dab50be..00000000000 --- a/packages/react-docgen/src/utils/isReactCreateElementCall.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { CallExpression } from '@babel/types'; -import isReactBuiltinCall from './isReactBuiltinCall.js'; - -/** - * Returns true if the expression is a function call of the form - * `React.createElement(...)`. - */ -export default function isReactCreateElementCall( - path: NodePath, -): path is NodePath { - return isReactBuiltinCall(path, 'createElement'); -} diff --git a/packages/react-docgen/src/utils/isReactForwardRefCall.ts b/packages/react-docgen/src/utils/isReactForwardRefCall.ts deleted file mode 100644 index c46802aaf9f..00000000000 --- a/packages/react-docgen/src/utils/isReactForwardRefCall.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import isReactBuiltinCall from './isReactBuiltinCall.js'; -import type { CallExpression } from '@babel/types'; - -/** - * Returns true if the expression is a function call of the form - * `React.forwardRef(...)`. - */ -export default function isReactForwardRefCall( - path: NodePath, -): path is NodePath { - return ( - isReactBuiltinCall(path, 'forwardRef') && - (path as NodePath).get('arguments').length === 1 - ); -} diff --git a/packages/react-docgen/src/utils/isReactModuleName.ts b/packages/react-docgen/src/utils/isReactModuleName.ts deleted file mode 100644 index 6261737027c..00000000000 --- a/packages/react-docgen/src/utils/isReactModuleName.ts +++ /dev/null @@ -1,15 +0,0 @@ -const reactModules = [ - 'react', - 'react/addons', - 'react-native', - 'proptypes', - 'prop-types', -]; - -/** - * Takes a module name (string) and returns true if it refers to a root react - * module name. - */ -export default function isReactModuleName(moduleName: string): boolean { - return reactModules.includes(moduleName.toLowerCase()); -} diff --git a/packages/react-docgen/src/utils/isRequiredPropType.ts b/packages/react-docgen/src/utils/isRequiredPropType.ts deleted file mode 100644 index 7458dc9b8ca..00000000000 --- a/packages/react-docgen/src/utils/isRequiredPropType.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import getMembers from '../utils/getMembers.js'; - -/** - * Returns true of the prop is required, according to its type definition - */ -export default function isRequiredPropType(path: NodePath): boolean { - return getMembers(path).some( - ({ computed, path: memberPath }) => - (!computed && memberPath.isIdentifier({ name: 'isRequired' })) || - memberPath.isStringLiteral({ value: 'isRequired' }), - ); -} diff --git a/packages/react-docgen/src/utils/isStatelessComponent.ts b/packages/react-docgen/src/utils/isStatelessComponent.ts deleted file mode 100644 index bc97eae4826..00000000000 --- a/packages/react-docgen/src/utils/isStatelessComponent.ts +++ /dev/null @@ -1,42 +0,0 @@ -import isReactCreateElementCall from './isReactCreateElementCall.js'; -import isReactCloneElementCall from './isReactCloneElementCall.js'; -import isReactChildrenElementCall from './isReactChildrenElementCall.js'; -import type { NodePath } from '@babel/traverse'; -import type { StatelessComponentNode } from '../resolver/index.js'; -import findFunctionReturn from './findFunctionReturn.js'; -import type { CallExpression, JSXElement, JSXFragment } from '@babel/types'; - -const validPossibleStatelessComponentTypes = [ - 'ArrowFunctionExpression', - 'FunctionDeclaration', - 'FunctionExpression', - 'ObjectMethod', -]; - -function isJSXElementOrReactCall( - path: NodePath, -): path is NodePath { - return ( - path.isJSXElement() || - path.isJSXFragment() || - (path.isCallExpression() && - (isReactCreateElementCall(path) || - isReactCloneElementCall(path) || - isReactChildrenElementCall(path))) - ); -} - -/** - * Returns `true` if the path represents a function which returns a JSXElement - */ -export default function isStatelessComponent( - path: NodePath, -): path is NodePath { - if (!path.inType(...validPossibleStatelessComponentTypes)) { - return false; - } - - const foundPath = findFunctionReturn(path, isJSXElementOrReactCall); - - return Boolean(foundPath); -} diff --git a/packages/react-docgen/src/utils/isUnreachableFlowType.ts b/packages/react-docgen/src/utils/isUnreachableFlowType.ts deleted file mode 100644 index bfed1bfcc19..00000000000 --- a/packages/react-docgen/src/utils/isUnreachableFlowType.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { NodePath } from '@babel/traverse'; - -/** - * Returns true of the path is an unreachable TypePath - * This evaluates the NodePaths returned from resolveToValue - */ -export default (path: NodePath): boolean => { - return ( - path.isIdentifier() || - path.parentPath?.isImportDeclaration() || - path.isCallExpression() - ); -}; diff --git a/packages/react-docgen/src/utils/normalizeClassDefinition.ts b/packages/react-docgen/src/utils/normalizeClassDefinition.ts deleted file mode 100644 index 5704fcc47d3..00000000000 --- a/packages/react-docgen/src/utils/normalizeClassDefinition.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { classProperty, inheritsComments } from '@babel/types'; -import getMemberExpressionRoot from '../utils/getMemberExpressionRoot.js'; -import getMembers from '../utils/getMembers.js'; -import type { NodePath } from '@babel/traverse'; -import { visitors } from '@babel/traverse'; -import type { - ClassDeclaration, - ClassExpression, - Expression, -} from '@babel/types'; -import { ignore } from './traverse.js'; - -interface TraverseState { - readonly variableName: string; - readonly classDefinition: NodePath; -} - -const explodedVisitors = visitors.explode({ - Function: { enter: ignore }, - Class: { enter: ignore }, - Loop: { enter: ignore }, - AssignmentExpression(path, state) { - const left = path.get('left'); - - if (left.isMemberExpression()) { - const first = getMemberExpressionRoot(left); - - if (first.isIdentifier({ name: state.variableName })) { - const [member] = getMembers(left); - - if ( - member && - !member.path.has('computed') && - !member.path.isPrivateName() - ) { - const property = classProperty( - member.path.node as Expression, - path.node.right, - null, - null, - false, - true, - ); - - inheritsComments(property, path.node); - if (path.parentPath.isExpressionStatement()) { - inheritsComments(property, path.parentPath.node); - } - - state.classDefinition.get('body').unshiftContainer('body', property); - path.skip(); - path.remove(); - } - } - } else { - path.skip(); - } - }, -}); - -/** - * Given a class definition (i.e. `class` declaration or expression), this - * function "normalizes" the definition, by looking for assignments of static - * properties and converting them to ClassProperties. - * - * Example: - * - * class MyComponent extends React.Component { - * // ... - * } - * MyComponent.propTypes = { ... }; - * - * is converted to - * - * class MyComponent extends React.Component { - * // ... - * static propTypes = { ... }; - * } - */ -export default function normalizeClassDefinition( - classDefinition: NodePath, -): void { - let variableName: string | undefined; - - if (classDefinition.isClassDeclaration()) { - // Class declarations may not have an id, e.g.: `export default class extends React.Component {}` - if (classDefinition.node.id) { - variableName = classDefinition.node.id.name; - } - } else if (classDefinition.isClassExpression()) { - let parentPath: NodePath | null = classDefinition.parentPath; - - while ( - parentPath && - parentPath.node !== classDefinition.scope.block && - !parentPath.isBlockStatement() - ) { - if (parentPath.isVariableDeclarator()) { - const idPath = parentPath.get('id'); - - if (idPath.isIdentifier()) { - variableName = idPath.node.name; - break; - } - } else if (parentPath.isAssignmentExpression()) { - const leftPath = parentPath.get('left'); - - if (leftPath.isIdentifier()) { - variableName = leftPath.node.name; - break; - } - } - parentPath = parentPath.parentPath; - } - } - - if (!variableName) { - return; - } - - const state: TraverseState = { - variableName, - classDefinition, - }; - - classDefinition.parentPath.scope.path.traverse(explodedVisitors, state); -} diff --git a/packages/react-docgen/src/utils/parseJsDoc.ts b/packages/react-docgen/src/utils/parseJsDoc.ts deleted file mode 100644 index 62174e51927..00000000000 --- a/packages/react-docgen/src/utils/parseJsDoc.ts +++ /dev/null @@ -1,131 +0,0 @@ -import doctrine from 'doctrine'; -import type { Type, Annotation, Tag } from 'doctrine'; - -type ExcludesNullish = (x: T | 0 | false | null | undefined) => x is T; -type JsDocType = JsDocBaseType | JsDocElementsType; - -interface JsDocBaseType { - name: string; -} - -interface JsDocElementsType extends JsDocBaseType { - elements: JsDocType[]; -} - -interface JsDocProperty { - description: string | null; - type: JsDocType | null; -} -interface JsDocParam extends JsDocProperty { - name: string; - optional?: boolean; -} - -interface JsDoc { - description: string | null; - params: JsDocParam[]; - returns: JsDocProperty | null; -} - -function getType(tagType: Type | null | undefined): JsDocType | null { - if (!tagType) { - return null; - } - - switch (tagType.type) { - case 'NameExpression': - // {a} - return { name: tagType.name }; - case 'UnionType': - // {a|b} - return { - name: 'union', - elements: tagType.elements - .map((element) => getType(element)) - .filter(Boolean as unknown as ExcludesNullish), - }; - case 'AllLiteral': - // {*} - return { name: 'mixed' }; - case 'TypeApplication': - // {Array} or {string[]} - return { - name: 'name' in tagType.expression ? tagType.expression.name : '', - elements: tagType.applications - .map((element) => getType(element)) - .filter(Boolean as unknown as ExcludesNullish), - }; - case 'ArrayType': - // {[number, string]} - return { - name: 'tuple', - elements: tagType.elements - .map((element) => getType(element)) - .filter(Boolean as unknown as ExcludesNullish), - }; - default: { - const typeName = - 'name' in tagType && tagType.name - ? tagType.name - : 'expression' in tagType && - tagType.expression && - 'name' in tagType.expression - ? tagType.expression.name - : null; - - if (typeName) { - return { name: typeName }; - } else { - return null; - } - } - } -} - -function getOptional(tag: Tag): boolean { - return !!(tag.type && tag.type.type && tag.type.type === 'OptionalType'); -} - -// Add jsdoc @return description. -function getReturnsJsDoc(jsDoc: Annotation): JsDocProperty | null { - const returnTag = jsDoc.tags.find( - (tag) => tag.title === 'return' || tag.title === 'returns', - ); - - if (returnTag) { - return { - description: returnTag.description, - type: getType(returnTag.type), - }; - } - - return null; -} - -// Add jsdoc @param descriptions. -function getParamsJsDoc(jsDoc: Annotation): JsDocParam[] { - if (!jsDoc.tags) { - return []; - } - - return jsDoc.tags - .filter((tag) => tag.title === 'param') - .map((tag) => { - return { - name: tag.name || '', - description: tag.description, - type: getType(tag.type), - optional: getOptional(tag), - }; - }); -} - -export default function parseJsDoc(docblock: string): JsDoc { - const jsDoc = doctrine.parse(docblock); - - return { - description: jsDoc.description || null, - params: getParamsJsDoc(jsDoc), - returns: getReturnsJsDoc(jsDoc), - }; -} diff --git a/packages/react-docgen/src/utils/postProcessDocumentation.ts b/packages/react-docgen/src/utils/postProcessDocumentation.ts deleted file mode 100644 index 264200ea8c3..00000000000 --- a/packages/react-docgen/src/utils/postProcessDocumentation.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { Documentation } from '../Documentation.js'; - -export default function (documentation: Documentation): Documentation { - const props = documentation.props; - - if (props) { - Object.values(props).forEach((propInfo) => { - // props with default values should not be required - if (propInfo.defaultValue) { - propInfo.required = false; - } - }); - } - - return documentation; -} diff --git a/packages/react-docgen/src/utils/printValue.ts b/packages/react-docgen/src/utils/printValue.ts deleted file mode 100644 index 5a524d8626d..00000000000 --- a/packages/react-docgen/src/utils/printValue.ts +++ /dev/null @@ -1,26 +0,0 @@ -import strip from 'strip-indent'; -import type { NodePath } from '@babel/traverse'; - -function deindent(code: string): string { - const firstNewLine = code.indexOf('\n'); - - return ( - code.slice(0, firstNewLine + 1) + - // remove indentation from all lines except first. - strip(code.slice(firstNewLine + 1)) - ); -} - -/** - * Prints the given path without leading or trailing comments. - */ -export default function printValue(path: NodePath): string { - let source = path.getSource(); - - // variable declarations and interface/type/class members might end with one of these - if (source.endsWith(',') || source.endsWith(';')) { - source = source.slice(0, -1); - } - - return deindent(source); -} diff --git a/packages/react-docgen/src/utils/resolveExportDeclaration.ts b/packages/react-docgen/src/utils/resolveExportDeclaration.ts deleted file mode 100644 index 5081ab23ef9..00000000000 --- a/packages/react-docgen/src/utils/resolveExportDeclaration.ts +++ /dev/null @@ -1,36 +0,0 @@ -import resolveToValue from './resolveToValue.js'; -import type { - ExportDefaultDeclaration, - ExportNamedDeclaration, -} from '@babel/types'; -import type { NodePath } from '@babel/traverse'; - -export default function resolveExportDeclaration( - path: NodePath, -): NodePath[] { - const definitions: NodePath[] = []; - - if (path.isExportDefaultDeclaration()) { - definitions.push(path.get('declaration')); - } else if (path.isExportNamedDeclaration()) { - if (path.has('declaration')) { - const declaration = path.get('declaration'); - - if (declaration.isVariableDeclaration()) { - declaration - .get('declarations') - .forEach((declarator) => definitions.push(declarator)); - } else if (declaration.isDeclaration()) { - definitions.push(declaration); - } - } else if (path.has('specifiers')) { - path.get('specifiers').forEach((specifier) => { - if (specifier.isExportSpecifier()) { - definitions.push(specifier.get('local')); - } - }); - } - } - - return definitions.map((definition) => resolveToValue(definition)); -} diff --git a/packages/react-docgen/src/utils/resolveFunctionDefinitionToReturnValue.ts b/packages/react-docgen/src/utils/resolveFunctionDefinitionToReturnValue.ts deleted file mode 100644 index ab8c6a66f1d..00000000000 --- a/packages/react-docgen/src/utils/resolveFunctionDefinitionToReturnValue.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import { visitors } from '@babel/traverse'; -import type { Expression, Function as BabelFunction } from '@babel/types'; -import resolveToValue from './resolveToValue.js'; -import { ignore, shallowIgnoreVisitors } from './traverse.js'; - -interface TraverseState { - returnPath?: NodePath; -} - -const explodedVisitors = visitors.explode({ - ...shallowIgnoreVisitors, - - Function: { enter: ignore }, - ReturnStatement: { - enter: function (nodePath, state) { - const argument = nodePath.get('argument'); - - if (argument.hasNode()) { - state.returnPath = resolveToValue(argument) as NodePath; - - return nodePath.stop(); - } - - nodePath.skip(); - }, - }, -}); - -export default function resolveFunctionDefinitionToReturnValue( - path: NodePath, -): NodePath | null { - const body = path.get('body'); - const state: TraverseState = {}; - - body.traverse(explodedVisitors, state); - - return state.returnPath || null; -} diff --git a/packages/react-docgen/src/utils/resolveGenericTypeAnnotation.ts b/packages/react-docgen/src/utils/resolveGenericTypeAnnotation.ts deleted file mode 100644 index 3b0c7267cb7..00000000000 --- a/packages/react-docgen/src/utils/resolveGenericTypeAnnotation.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import isUnreachableFlowType from '../utils/isUnreachableFlowType.js'; -import resolveToValue from '../utils/resolveToValue.js'; -import { unwrapUtilityType } from './flowUtilityTypes.js'; -import getTypeIdentifier from './getTypeIdentifier.js'; - -function tryResolveGenericTypeAnnotation(path: NodePath): NodePath | undefined { - let typePath = unwrapUtilityType(path); - const idPath = getTypeIdentifier(typePath); - - if (idPath) { - typePath = resolveToValue(idPath); - if (isUnreachableFlowType(typePath)) { - return; - } - - if (typePath.isTypeAlias()) { - return tryResolveGenericTypeAnnotation(typePath.get('right')); - } else if (typePath.isTSTypeAliasDeclaration()) { - return tryResolveGenericTypeAnnotation(typePath.get('typeAnnotation')); - } - - return typePath; - } - - return typePath; -} - -/** - * Given an React component (stateless or class) tries to find the - * flow or ts type for the props. If not found or not one of the supported - * component types returns undefined. - */ -export default function resolveGenericTypeAnnotation( - path: NodePath, -): NodePath | undefined { - const typePath = tryResolveGenericTypeAnnotation(path); - - if (!typePath || typePath === path) return; - - return typePath; -} diff --git a/packages/react-docgen/src/utils/resolveHOC.ts b/packages/react-docgen/src/utils/resolveHOC.ts deleted file mode 100644 index 3ca3222e793..00000000000 --- a/packages/react-docgen/src/utils/resolveHOC.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import isReactCreateClassCall from './isReactCreateClassCall.js'; -import isReactForwardRefCall from './isReactForwardRefCall.js'; -import resolveToValue from './resolveToValue.js'; - -/** - * If the path is a call expression, it recursively resolves to the - * rightmost argument, stopping if it finds a React.createClass call expression - * - * Else the path itself is returned. - */ -export default function resolveHOC(path: NodePath): NodePath { - if ( - path.isCallExpression() && - !isReactCreateClassCall(path) && - !isReactForwardRefCall(path) - ) { - const node = path.node; - const argumentLength = node.arguments.length; - - if (argumentLength && argumentLength > 0) { - const args = path.get('arguments'); - const firstArg = args[0]!; - - // If the first argument is one of these types then the component might be the last argument - // If there are all identifiers then we cannot figure out exactly and have to assume it is the first - if ( - argumentLength > 1 && - (firstArg.isLiteral() || - firstArg.isObjectExpression() || - firstArg.isArrayExpression() || - firstArg.isSpreadElement()) - ) { - return resolveHOC(resolveToValue(args[argumentLength - 1]!)); - } - - return resolveHOC(resolveToValue(firstArg)); - } - } - - return path; -} diff --git a/packages/react-docgen/src/utils/resolveObjectKeysToArray.ts b/packages/react-docgen/src/utils/resolveObjectKeysToArray.ts deleted file mode 100644 index b6e0fc03a29..00000000000 --- a/packages/react-docgen/src/utils/resolveObjectKeysToArray.ts +++ /dev/null @@ -1,163 +0,0 @@ -import resolveToValue from './resolveToValue.js'; -import type { NodePath } from '@babel/traverse'; -import type { - CallExpression, - Identifier, - NumericLiteral, - StringLiteral, -} from '@babel/types'; - -function isObjectKeysCall(path: NodePath): path is NodePath { - if (!path.isCallExpression() || path.get('arguments').length !== 1) { - return false; - } - - const callee = path.get('callee'); - - if (!callee.isMemberExpression()) { - return false; - } - const object = callee.get('object'); - const property = callee.get('property'); - - return ( - object.isIdentifier({ name: 'Object' }) && - property.isIdentifier({ name: 'keys' }) - ); -} - -function isWhitelistedObjectProperty(path: NodePath): boolean { - if (path.isSpreadElement()) return true; - - if ( - path.isObjectProperty() || - (path.isObjectMethod() && - (path.node.kind === 'get' || path.node.kind === 'set')) - ) { - const key = path.get('key') as NodePath; - - return ( - (key.isIdentifier() && !path.node.computed) || - key.isStringLiteral() || - key.isNumericLiteral() - ); - } - - return false; -} - -function isWhiteListedObjectTypeProperty(path: NodePath): boolean { - return ( - path.isObjectTypeProperty() || - path.isObjectTypeSpreadProperty() || - path.isTSPropertySignature() - ); -} - -// Resolves an ObjectExpression or an ObjectTypeAnnotation -export function resolveObjectToNameArray( - objectPath: NodePath, - raw = false, -): string[] | null { - if ( - (objectPath.isObjectExpression() && - objectPath.get('properties').every(isWhitelistedObjectProperty)) || - (objectPath.isObjectTypeAnnotation() && - objectPath.get('properties').every(isWhiteListedObjectTypeProperty)) || - (objectPath.isTSTypeLiteral() && - objectPath.get('members').every(isWhiteListedObjectTypeProperty)) - ) { - let values: string[] = []; - let error = false; - const properties = objectPath.isTSTypeLiteral() - ? objectPath.get('members') - : (objectPath.get('properties') as NodePath[]); - - properties.forEach((propPath) => { - if (error) return; - - if ( - propPath.isObjectProperty() || - propPath.isObjectMethod() || - propPath.isObjectTypeProperty() || - propPath.isTSPropertySignature() - ) { - const key = propPath.get('key') as - | NodePath - | NodePath - | NodePath; - // Key is either Identifier or Literal - const name: string = key.isIdentifier() - ? key.node.name - : raw - ? (key.node.extra?.raw as string) - : `${key.node.value}`; - - values.push(name); - } else if ( - propPath.isSpreadElement() || - propPath.isObjectTypeSpreadProperty() - ) { - let spreadObject = resolveToValue(propPath.get('argument') as NodePath); - - if (spreadObject.isGenericTypeAnnotation()) { - const typeAliasRight = resolveToValue(spreadObject.get('id')).get( - 'right', - ) as NodePath; - - if (typeAliasRight.isObjectTypeAnnotation()) { - spreadObject = resolveToValue(typeAliasRight); - } - } - - const spreadValues = resolveObjectToNameArray(spreadObject); - - if (!spreadValues) { - error = true; - - return; - } - values = [...values, ...spreadValues]; - } - }); - - if (!error) { - return values; - } - } - - return null; -} - -/** - * Returns an ArrayExpression which contains all the keys resolved from an object - * - * Ignores setters in objects - * - * Returns null in case of - * unresolvable spreads - * computed identifier keys - */ -export default function resolveObjectKeysToArray( - path: NodePath, -): string[] | null { - if (isObjectKeysCall(path)) { - const argument = path.get('arguments')[0]; - const objectExpression = resolveToValue( - // isObjectKeysCall already asserts that there is at least one argument, hence the non-null-assertion - argument!, - ); - const values = resolveObjectToNameArray(objectExpression); - - if (values) { - const nodes = values - //filter duplicates - .filter((value, index, array) => array.indexOf(value) === index) - .map((value) => `"${value}"`); - - return nodes; - } - } - - return null; -} diff --git a/packages/react-docgen/src/utils/resolveObjectPatternPropertyToValue.ts b/packages/react-docgen/src/utils/resolveObjectPatternPropertyToValue.ts deleted file mode 100644 index c8304ce70e4..00000000000 --- a/packages/react-docgen/src/utils/resolveObjectPatternPropertyToValue.ts +++ /dev/null @@ -1,48 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { Identifier, ObjectProperty } from '@babel/types'; -import getPropertyValuePath from './getPropertyValuePath.js'; -import resolveToValue from './resolveToValue.js'; - -function resolveToObjectExpression(path: NodePath): NodePath | null { - if (path.isVariableDeclarator()) { - const init = path.get('init'); - - if (init.hasNode()) { - return resolveToValue(init); - } - } else if (path.isAssignmentExpression()) { - if (path.node.operator === '=') { - return resolveToValue(path.get('right')); - } - } - - return null; -} - -/** - * Resolve and ObjectProperty inside an ObjectPattern to its value if possible - * If not found `null` is returned - */ -export default function resolveObjectPatternPropertyToValue( - path: NodePath, -): NodePath | null { - if (!path.parentPath.isObjectPattern()) { - return null; - } - - const resolved = resolveToObjectExpression(path.parentPath.parentPath); - - if (resolved && resolved.isObjectExpression()) { - const propertyPath = getPropertyValuePath( - resolved, - // Always id in ObjectPattern - (path.get('key') as NodePath).node.name, - ); - - if (propertyPath) { - return resolveToValue(propertyPath); - } - } - - return null; -} diff --git a/packages/react-docgen/src/utils/resolveObjectValuesToArray.ts b/packages/react-docgen/src/utils/resolveObjectValuesToArray.ts deleted file mode 100644 index 0838abc15ad..00000000000 --- a/packages/react-docgen/src/utils/resolveObjectValuesToArray.ts +++ /dev/null @@ -1,115 +0,0 @@ -import resolveToValue from './resolveToValue.js'; -import type { NodePath } from '@babel/traverse'; -import type { - CallExpression, - Identifier, - NumericLiteral, - StringLiteral, -} from '@babel/types'; - -function isObjectValuesCall(path: NodePath): path is NodePath { - if (!path.isCallExpression() || path.node.arguments.length !== 1) { - return false; - } - - const callee = path.get('callee'); - - if (!callee.isMemberExpression()) { - return false; - } - const object = callee.get('object'); - const property = callee.get('property'); - - return ( - object.isIdentifier({ name: 'Object' }) && - property.isIdentifier({ name: 'values' }) - ); -} - -// Resolves an ObjectExpression or an ObjectTypeAnnotation -function resolveObjectToPropMap(object: NodePath): Map | null { - if (object.isObjectExpression()) { - const values = new Map(); - let error = false; - - object.get('properties').forEach((propPath) => { - if (error || propPath.isObjectMethod()) return; - - if (propPath.isObjectProperty()) { - const key = propPath.get('key') as NodePath< - Identifier | NumericLiteral | StringLiteral - >; - let name: string; - - // Key is either Identifier or Literal - if (key.isIdentifier()) { - name = key.node.name; - } else if (key.isNumericLiteral() || key.isStringLiteral()) { - name = `${key.node.value}`; - } else { - error = true; - - return; - } - - const valuePath = resolveToValue(propPath.get('value')); - const value = valuePath.isStringLiteral() - ? `"${valuePath.node.value}"` - : valuePath.isNumericLiteral() - ? `${valuePath.node.value}` - : // we return null here because there are a lot of cases and we don't know yet what we need to handle - 'null'; - - values.set(name, value); - } else if (propPath.isSpreadElement()) { - const spreadObject = resolveToValue(propPath.get('argument')); - const spreadValues = resolveObjectToPropMap(spreadObject); - - if (!spreadValues) { - error = true; - - return; - } - for (const entry of spreadValues.entries()) { - const [key, value] = entry; - - values.set(key, value); - } - } - }); - - if (!error) { - return values; - } - } - - return null; -} - -/** - * Returns an ArrayExpression which contains all the values resolved from an object - * - * Ignores setters in objects - * - * Returns null in case of - * unresolvable spreads - * computed identifier values - */ -export default function resolveObjectValuesToArray( - path: NodePath, -): string[] | null { - if (isObjectValuesCall(path)) { - const argument = path.get('arguments')[0]; - const objectExpression = resolveToValue( - // isObjectValuesCall already asserts that there is at least one argument, hence the non-null-assertion - argument!, - ); - const values = resolveObjectToPropMap(objectExpression); - - if (values) { - return Array.from(values.values()); - } - } - - return null; -} diff --git a/packages/react-docgen/src/utils/resolveToModule.ts b/packages/react-docgen/src/utils/resolveToModule.ts deleted file mode 100644 index a2be996c464..00000000000 --- a/packages/react-docgen/src/utils/resolveToModule.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type { Expression, StringLiteral } from '@babel/types'; -import getMemberExpressionRoot from './getMemberExpressionRoot.js'; -import resolveToValue from './resolveToValue.js'; - -/** - * Given a path (e.g. call expression, member expression or identifier), - * this function tries to find the name of module from which the "root value" - * was imported. - */ -export default function resolveToModule(path: NodePath): string | null { - if (path.isVariableDeclarator()) { - if (path.node.init) { - return resolveToModule(path.get('init') as NodePath); - } - } else if (path.isCallExpression()) { - const callee = path.get('callee'); - - if (callee.isIdentifier({ name: 'require' })) { - return (path.node.arguments[0] as StringLiteral).value; - } - - return resolveToModule(callee); - } else if (path.isIdentifier() || path.isJSXIdentifier()) { - const valuePath = resolveToValue(path); - - if (valuePath !== path) { - return resolveToModule(valuePath); - } - if (path.parentPath.isObjectProperty()) { - return resolveToModule(path.parentPath); - } - } else if (path.isObjectProperty() || path.isObjectPattern()) { - return resolveToModule(path.parentPath); - } else if (path.parentPath?.isImportDeclaration()) { - return path.parentPath.node.source.value; - } else if (path.isMemberExpression()) { - path = getMemberExpressionRoot(path); - - return resolveToModule(path); - } - - return null; -} diff --git a/packages/react-docgen/src/utils/resolveToValue.ts b/packages/react-docgen/src/utils/resolveToValue.ts deleted file mode 100644 index d296fa089f9..00000000000 --- a/packages/react-docgen/src/utils/resolveToValue.ts +++ /dev/null @@ -1,232 +0,0 @@ -import { Scope, visitors } from '@babel/traverse'; -import type { NodePath } from '@babel/traverse'; -import type { Identifier, ImportDeclaration } from '@babel/types'; -import getMemberExpressionRoot from './getMemberExpressionRoot.js'; -import getPropertyValuePath from './getPropertyValuePath.js'; -import { Array as toArray } from './expressionTo.js'; -import { shallowIgnoreVisitors } from './traverse.js'; -import getMemberValuePath, { - isSupportedDefinitionType, -} from './getMemberValuePath.js'; -import initialize from './ts-types/index.js'; -import getNameOrValue from './getNameOrValue.js'; - -function findScopePath( - bindingIdentifiers: Array> | undefined, -): NodePath | null { - if (bindingIdentifiers && bindingIdentifiers[0]) { - const resolvedParentPath = bindingIdentifiers[0].parentPath; - - if ( - resolvedParentPath.isImportDefaultSpecifier() || - resolvedParentPath.isImportSpecifier() - ) { - let exportName: string | undefined; - - if (resolvedParentPath.isImportDefaultSpecifier()) { - exportName = 'default'; - } else { - const imported = resolvedParentPath.get('imported'); - - if (imported.isStringLiteral()) { - exportName = imported.node.value; - } else if (imported.isIdentifier()) { - exportName = imported.node.name; - } - } - - if (!exportName) { - throw new Error('Could not detect export name'); - } - - const importedPath = resolvedParentPath.hub.import( - resolvedParentPath.parentPath as NodePath, - exportName, - ); - - if (importedPath) { - return resolveToValue(importedPath); - } - } - - return resolveToValue(resolvedParentPath); - } - - return null; -} - -interface TraverseState { - readonly idPath: NodePath; - resultPath?: NodePath; -} - -const explodedVisitors = visitors.explode({ - ...shallowIgnoreVisitors, - - AssignmentExpression: { - enter: function (assignmentPath, state) { - const node = state.idPath.node; - const left = assignmentPath.get('left'); - - // Skip anything that is not an assignment to a variable with the - // passed name. - // Ensure the LHS isn't the reference we're trying to resolve. - if ( - !left.isIdentifier() || - left.node === node || - left.node.name !== node.name || - assignmentPath.node.operator !== '=' - ) { - return assignmentPath.skip(); - } - // Ensure the RHS doesn't contain the reference we're trying to resolve. - const candidatePath = assignmentPath.get('right'); - - if ( - candidatePath.node === node || - state.idPath.findParent((parent) => parent.node === candidatePath.node) - ) { - return assignmentPath.skip(); - } - - state.resultPath = candidatePath; - - return assignmentPath.skip(); - }, - }, -}); - -/** - * Tries to find the last value assigned to `name` in the scope created by - * `scope`. We are not descending into any statements (blocks). - */ -function findLastAssignedValue( - path: NodePath, - idPath: NodePath, -): NodePath | null { - const state: TraverseState = { idPath }; - - path.traverse(explodedVisitors, state); - - return state.resultPath ? resolveToValue(state.resultPath) : null; -} - -/** - * If the path is an identifier, it is resolved in the scope chain. - * If it is an assignment expression, it resolves to the right hand side. - * If it is a member expression it is resolved to it's initialization value. - * - * Else the path itself is returned. - */ -export default function resolveToValue(path: NodePath): NodePath { - if (path.isIdentifier()) { - if ( - (path.parentPath.isClass() || path.parentPath.isFunction()) && - path.parentPath.get('id') === path - ) { - return path.parentPath; - } - - const binding = path.scope.getBinding(path.node.name); - let resolvedPath: NodePath | null = null; - - if (binding) { - // The variable may be assigned a different value after initialization. - // We are first trying to find all assignments to the variable in the - // block where it is defined (i.e. we are not traversing into statements) - resolvedPath = findLastAssignedValue(binding.scope.path, path); - if (!resolvedPath) { - const bindingMap = binding.path.getOuterBindingIdentifierPaths(true); - - resolvedPath = findScopePath(bindingMap[path.node.name]); - } - } else { - // Initialize our monkey-patching of @babel/traverse 🙈 - initialize(Scope); - const typeBinding = path.scope.getTypeBinding(path.node.name); - - if (typeBinding) { - resolvedPath = findScopePath([typeBinding.identifierPath]); - } - } - - return resolvedPath || path; - } else if (path.isVariableDeclarator()) { - const init = path.get('init'); - - if (init.hasNode()) { - return resolveToValue(init); - } - } else if (path.isMemberExpression()) { - const root = getMemberExpressionRoot(path); - const resolved = resolveToValue(root); - - if (resolved.isObjectExpression()) { - let propertyPath: NodePath | null = resolved; - - for (const propertyName of toArray(path).slice(1)) { - if (propertyPath && propertyPath.isObjectExpression()) { - propertyPath = getPropertyValuePath(propertyPath, propertyName); - } - if (!propertyPath) { - return path; - } - propertyPath = resolveToValue(propertyPath); - } - - return propertyPath; - } else if (isSupportedDefinitionType(resolved)) { - const property = path.get('property'); - - if (property.isIdentifier() || property.isStringLiteral()) { - const memberPath = getMemberValuePath( - resolved, - property.isIdentifier() ? property.node.name : property.node.value, - ); - - if (memberPath) { - return resolveToValue(memberPath); - } - } - } else if ( - resolved.isImportSpecifier() || - resolved.isImportDefaultSpecifier() || - resolved.isImportNamespaceSpecifier() - ) { - const declaration = resolved.parentPath as NodePath; - - // Handle references to namespace imports, e.g. import * as foo from 'bar'. - // Try to find a specifier that matches the root of the member expression, and - // find the export that matches the property name. - for (const specifier of declaration.get('specifiers')) { - const property = path.get('property'); - let propertyName: string | undefined; - - if (property.isIdentifier() || property.isStringLiteral()) { - propertyName = getNameOrValue(property) as string; - } - - if ( - specifier.isImportNamespaceSpecifier() && - root.isIdentifier() && - propertyName && - specifier.node.local.name === root.node.name - ) { - const resolvedPath = path.hub.import(declaration, propertyName); - - if (resolvedPath) { - return resolveToValue(resolvedPath); - } - } - } - } - } else if ( - path.isTypeCastExpression() || - path.isTSAsExpression() || - path.isTSTypeAssertion() - ) { - return resolveToValue(path.get('expression') as NodePath); - } - - return path; -} diff --git a/packages/react-docgen/src/utils/setPropDescription.ts b/packages/react-docgen/src/utils/setPropDescription.ts deleted file mode 100644 index d6b023aea57..00000000000 --- a/packages/react-docgen/src/utils/setPropDescription.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import type Documentation from '../Documentation.js'; -import getPropertyName from './getPropertyName.js'; -import { getDocblock } from './docblock.js'; -import type { - ObjectMethod, - ObjectProperty, - ObjectTypeProperty, - TSPropertySignature, -} from '@babel/types'; - -export default function setPropDescription( - documentation: Documentation, - propertyPath: NodePath< - ObjectMethod | ObjectProperty | ObjectTypeProperty | TSPropertySignature - >, -): void { - const propName = getPropertyName(propertyPath); - - if (!propName) return; - - const propDescriptor = documentation.getPropDescriptor(propName); - - if (propDescriptor.description) return; - - propDescriptor.description = getDocblock(propertyPath) || ''; -} diff --git a/packages/react-docgen/src/utils/traverse.ts b/packages/react-docgen/src/utils/traverse.ts deleted file mode 100644 index 3066ac486ce..00000000000 --- a/packages/react-docgen/src/utils/traverse.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { NodePath } from '@babel/traverse'; - -export function ignore(path: NodePath): void { - path.skip(); -} - -export const shallowIgnoreVisitors = { - FunctionDeclaration: { enter: ignore }, - FunctionExpression: { enter: ignore }, - Class: { enter: ignore }, - IfStatement: { enter: ignore }, - WithStatement: { enter: ignore }, - SwitchStatement: { enter: ignore }, - CatchClause: { enter: ignore }, - Loop: { enter: ignore }, - ExportNamedDeclaration: { enter: ignore }, - ExportDefaultDeclaration: { enter: ignore }, - ConditionalExpression: { enter: ignore }, -}; diff --git a/packages/react-docgen/src/utils/ts-types/index.ts b/packages/react-docgen/src/utils/ts-types/index.ts deleted file mode 100644 index cb31aae5862..00000000000 --- a/packages/react-docgen/src/utils/ts-types/index.ts +++ /dev/null @@ -1,171 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import { Scope as BaseScope } from '@babel/traverse'; -import type { - Identifier, - TSEnumDeclaration, - TSInterfaceDeclaration, - TSTypeAliasDeclaration, -} from '@babel/types'; - -type BindingNode = - | TSEnumDeclaration - | TSInterfaceDeclaration - | TSTypeAliasDeclaration; - -type TypeKind = 'alias' | 'enum' | 'interface'; - -/** - * What the f... is this? - * Well, babel and in particular @babel/traverse have no scope tracking - * for typescript types. Flow types do work because they are part of the - * normal reference tracking and mix with non-type identifiers. - * This monkey-patching of @babel/traverse adds scope tracking for - * typescript types. It tries to do this without changing any babel behavior. - * - * This is not the best solution, but it allows to use @babel/traverse in react-docgen - * which needs to be able to do scope tracking of typescript types. - * - * see https://github.com/babel/babel/issues/14662 - */ - -declare module '@babel/traverse' { - export interface Scope { - typeBindings: Record; - getTypeBinding(name: string): TypeBinding | undefined; - getOwnTypeBinding(name: string): TypeBinding | undefined; - registerTypeBinding( - this: BaseScope, - typeKind: TypeKind, - path: NodePath, - bindingPath: NodePath, - ): void; - _realRegisterDeclaration: BaseScope['registerDeclaration']; - _realCrawl: BaseScope['crawl']; - } -} - -class TypeBinding { - identifier: Identifier; - identifierPath: NodePath; - path: NodePath; - scope: BaseScope; - typeKind: TypeKind; - - constructor(data: { - identifier: Identifier; - identifierPath: NodePath; - path: NodePath; - scope: BaseScope; - typeKind: TypeKind; - }) { - this.identifier = data.identifier; - this.identifierPath = data.identifierPath; - this.path = data.path; - this.scope = data.scope; - this.typeKind = data.typeKind; - } -} - -function registerTypeBinding( - this: BaseScope, - typeKind: TypeKind, - path: NodePath, - bindingPath: NodePath, -): void { - const id = path.node; - const { name } = id; - const local = this.getOwnTypeBinding(name); - - if (local) { - if (local.identifier === id) return; - - if ( - // : does collide, - // <=>: does not collide (type merging) - // - // enum interface - // enum alias - // interface alias - // alias alias - // interface <=> interface - // enum <=> enum - typeKind !== local.typeKind || - typeKind === 'alias' || - local.typeKind === 'alias' - ) { - throw this.hub.buildError( - id, - `Duplicate type declaration "${name}"`, - TypeError, - ); - } - } else { - this.typeBindings[name] = new TypeBinding({ - identifier: id, - identifierPath: path, - path: bindingPath, - scope: this, - typeKind, - }); - } -} - -function getTypeBinding( - this: BaseScope, - name: string, -): TypeBinding | undefined { - // eslint-disable-next-line @typescript-eslint/no-this-alias - let scope = this; - - do { - const binding = scope.getOwnTypeBinding(name); - - if (binding) { - return binding; - } - } while ((scope = scope.parent)); - - return undefined; -} - -function getOwnTypeBinding( - this: BaseScope, - name: string, -): TypeBinding | undefined { - return this.typeBindings[name]; -} - -function registerDeclaration(this: BaseScope, path: NodePath): void { - if (path.isTSTypeAliasDeclaration()) { - this.registerTypeBinding('alias', path.get('id'), path); - } else if (path.isTSInterfaceDeclaration()) { - this.registerTypeBinding('interface', path.get('id'), path); - } else if (path.isTSEnumDeclaration()) { - this.registerTypeBinding('enum', path.get('id'), path); - } else { - this._realRegisterDeclaration(path); - } -} - -export default function initialize(scopeClass: typeof BaseScope): void { - // @ts-expect-error The typ assumes getTypeBinding is always set, - // but we know we have to do that once and that is here - if (scopeClass.prototype.getTypeBinding) { - return; - } - scopeClass.prototype.getTypeBinding = getTypeBinding; - scopeClass.prototype.registerTypeBinding = registerTypeBinding; - scopeClass.prototype.getOwnTypeBinding = getOwnTypeBinding; - - scopeClass.prototype._realRegisterDeclaration = - scopeClass.prototype.registerDeclaration; - scopeClass.prototype.registerDeclaration = registerDeclaration; - - scopeClass.prototype._realCrawl = scopeClass.prototype.crawl; - scopeClass.prototype.crawl = function (this: BaseScope): void { - this.typeBindings = Object.create(null); - this._realCrawl(); - }; -} - -initialize(BaseScope); diff --git a/packages/react-docgen/src/utils/unwrapBuiltinTSPropTypes.ts b/packages/react-docgen/src/utils/unwrapBuiltinTSPropTypes.ts deleted file mode 100644 index 06f3cee24d4..00000000000 --- a/packages/react-docgen/src/utils/unwrapBuiltinTSPropTypes.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { NodePath } from '@babel/traverse'; -import isReactBuiltinReference from './isReactBuiltinReference.js'; - -/** - * Unwraps NodePaths from the builtin TS types `PropsWithoutRef`, - * `PropsWithRef` and `PropsWithChildren` and returns the inner type param. - * If none of the builtin types is detected the path is returned as-is - */ -export default function unwrapBuiltinTSPropTypes(typePath: NodePath): NodePath { - if (typePath.isTSTypeReference()) { - const typeName = typePath.get('typeName'); - - if ( - isReactBuiltinReference(typeName, 'PropsWithoutRef') || - isReactBuiltinReference(typeName, 'PropsWithRef') || - isReactBuiltinReference(typeName, 'PropsWithChildren') - ) { - const typeParameters = typePath.get('typeParameters'); - - if (typeParameters.hasNode()) { - const innerType = typeParameters.get('params')[0]; - - if (innerType) { - return unwrapBuiltinTSPropTypes(innerType); - } - } - } - } - - return typePath; -} diff --git a/packages/react-docgen/tests/NodePathSerializer.ts b/packages/react-docgen/tests/NodePathSerializer.ts deleted file mode 100644 index de0fc8fdf6d..00000000000 --- a/packages/react-docgen/tests/NodePathSerializer.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { NodePath } from '@babel/traverse'; -import { removePropertiesDeep } from '@babel/types'; -import type { expect } from 'vitest'; - -function removeUndefinedProperties( - node: Record, -): Record { - for (const key of Object.keys(node)) { - if (node[key] === undefined) { - // eslint-disable-next-line @typescript-eslint/no-dynamic-delete - delete node[key]; - } else if (node[key] === Object(node[key])) { - node[key] = removeUndefinedProperties( - node[key] as Record, - ); - } - } - - return node; -} - -export default { - serialize(val, config, indentation, depth, refs, printer) { - return printer( - removeUndefinedProperties(removePropertiesDeep(val.node)), - config, - indentation, - depth, - refs, - ); - }, - - test(val) { - return val && val instanceof NodePath; - }, -} as Parameters[0]; diff --git a/packages/react-docgen/tests/integration/__fixtures__/class-without-id.tsx b/packages/react-docgen/tests/integration/__fixtures__/class-without-id.tsx deleted file mode 100644 index 6c62d1d27cf..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/class-without-id.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import * as React from 'react'; - -interface IProps { - value: string; -} - -export default class extends React.Component { - render() { - return
; - } -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_1.js b/packages/react-docgen/tests/integration/__fixtures__/component_1.js deleted file mode 100644 index ea82ac1e24b..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_1.js +++ /dev/null @@ -1,12 +0,0 @@ -var Component, React; - -React = require('react'); - -/** - * The is a component to test the document generation - */ -Component = React.createClass({ - displayName: 'Component', -}); - -module.exports = Component; diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_10.js b/packages/react-docgen/tests/integration/__fixtures__/component_10.js deleted file mode 100644 index d78a04df46b..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_10.js +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Test for documentation of "arrow function methods." - */ - -import React, { Component } from 'react'; -import styled from 'styled-components'; - -/** - * React component that display current time at current location. - */ -class Clock extends Component { - - constructor(props){ - super(props); - const currentTime = new Date(); - this.state = this.getTime(); - } - - componentDidMount() { - this.setTimer(); - } - - componentWillUnmount(){ - // Avoiding timeout still runs when component is unmounted - if (this.timeOut) { - clearTimeout(this.timeOut); - } - } - - /** - * Update clock state with new time - * - */ - updateClock = () => { - const currentTime = this.getTime(); - this.setState(currentTime); - this.setTimer(); - } - - /** - * Parse current Date object - * - * @returns {Object} currentTime - * @returns {int} currentTime.hour - * @returns {int} currentTime.minutes - * @returns {string} currentTime.ampm "am" or "pm" - * @returns {string} currentTime.dayOfWeek - * @returns {string} currentTime.month - * @returns {int} currentTime.date - */ - getTime = () => { - const dateObject = new Date(); - const dateString = dateObject.toDateString().split(" "); - const currentTime = { - hours: dateObject.getHours(), - minutes: dateObject.getMinutes(), - seconds: dateObject.getSeconds(), - ampm: dateObject.getHours() >= 12 ? 'pm' : 'am', - dayOfWeek: dateString[0], - month: dateString[1], - date: dateString[2] - }; - - return currentTime; - } - - /** - * Update current clock for every 1 second - * - */ - setTimer = () => { - this.timeOut = setTimeout(()=> { - this.updateClock() - }, 1000); - } - - render(){ - const { - hours, - minutes, - seconds, - ampm, - dayOfWeek, - month, - date - } = this.state; - - const ClockContainer = styled.div` - color: #fff; - font-size: xx-large; - float: right; - top: 1em; - position: relative; - `; - - return( - - { this.props.title }
- { dayOfWeek }, { month } { date }
- { - hours == 0 ? 12 : - (hours >12) ? hours - 12 : hours - }: { - minutes > 9 ? minutes: `0${minutes}` - }: { - seconds > 9 ? seconds: `0${seconds}` - } {ampm}
- -
- ); - } -} - -Clock.propTypes = { - /** A text display current's user identity, - * "Nobody" if no one is detected in the background, - * "Hi, ..name" if an user is detected - */ - title: React.PropTypes.string -} - -export default Clock; diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_11.js b/packages/react-docgen/tests/integration/__fixtures__/component_11.js deleted file mode 100644 index fae874b9ae9..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_11.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Testing component using Flow - */ - -import React from 'react'; - -import { OtherComponentProps as OtherProps } from 'NonExistentFile'; - -type OtherLocalProps = {| - /** - * fooProp is spread in from a locally resolved type - */ - fooProp?: string, -|} - -type Props = {| - /** - * Spread props defined locally - */ - ...OtherLocalProps, - - /** - * Spread props from another file - */ - ...OtherProps, - - /** - * The first prop - */ - prop1: string, - - /** - * The second, covariant prop - */ - +prop2: number -|} - -class MyComponent extends React.Component { - render() { - return null; - } -} - -export default MyComponent; diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_12.js b/packages/react-docgen/tests/integration/__fixtures__/component_12.js deleted file mode 100644 index 5602c831cce..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_12.js +++ /dev/null @@ -1,101 +0,0 @@ -// @flow - -/** - * Test for documentation of flow class - */ - -import React from 'react'; -import type { ComponentType, ElementType, Node } from 'react'; - -type ProvidedProps = { - classes: Object, -}; - -export type Origin = { - horizontal: 'left' | 'center' | 'right' | number, - vertical: 'top' | 'center' | 'bottom' | number, -}; - -export const duration = { - standard: 300, -}; - -export type TransitionDuration = number | { enter?: number, exit?: number } | 'auto'; - -export type Props = { - /** - * Other base element props. - */ - [otherProp: string]: any, - /** - * This is the point on the anchor where the popover's - * `anchorEl` will attach to. This is not used when the - * anchorReference is 'anchorPosition'. - * - * Options: - * vertical: [top, center, bottom]; - * horizontal: [left, center, right]. - */ - anchorOrigin?: Origin, - /** - * Useful to extend the style applied to components. - */ - classes?: Object, - /** - * @ignore - */ - children?: Node, - /** - * The component used for the root node. - * This currently has to be flow cast in defaultProps as of flow 0.59.0 - */ - component: ElementType, - /** - * Shadow depth, corresponds to `dp` in the spec. - * It's accepting values between 0 and 24 inclusive. - */ - elevation: number, - /** - * Useful to customize the rows per page label. Invoked with a `{ from, to, count, page }` - * object. - */ - labelRowsPerPage: Node, - /** - * Transition component. - */ - transition: ComponentType<*>, - /** - * The duration for the transition, in milliseconds. - * You may specify a single timeout for all transitions, or individually with an object. - * - * Set to 'auto' to automatically calculate transition time based on height. - */ - timeout: TransitionDuration, -}; - -class Paper extends React.Component { - static defaultProps = { - anchorOrigin: ({ - vertical: 'top', - horizontal: 'left', - }: Origin), - labelRowsPerPage: ('Rows per page:': Node), - component: ('div': ElementType), - component: 'div', - elevation: 2, - timeout: (duration.standard: TransitionDuration), - }; - - render() { - const { - classes, - component: ComponentProp, - transition, - ...other - } = this.props; - - return ; - } -} - -export default Paper; \ No newline at end of file diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_13.js b/packages/react-docgen/tests/integration/__fixtures__/component_13.js deleted file mode 100644 index 891b53ece8b..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_13.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Test for documentation of React components with Flow annotations for props. - */ - -import React from 'react'; - -type AlignProps = {| - +align?: "left" | "center" | "right" | "justify", - +left?: boolean, - +center?: boolean, - +right?: boolean, - +justify?: boolean, -|}; - -type TransformProps = {| - +transform?: "lowercase" | "uppercase" | "capitalize", - +lowercase?: boolean, - +uppercase?: boolean, - +capitalize?: boolean, -|}; - -type TrackingProps = {| - +tracking?: "tight" | "normal" | "wide", - +trackingTight?: boolean, - +trackingNormal?: boolean, - +trackingWide?: boolean, -|}; - -type LeadingProps = {| - +leading?: "none" | "tight" | "normal" | "loose", - +leadingNone?: boolean, - +leadingTight?: boolean, - +leadingNormal?: boolean, - +leadingLoose?: boolean, -|}; - -type TextProps = {| - ...AlignProps, - ...TransformProps, - ...TrackingProps, - ...LeadingProps, - +children?: React.Node, - +className?: string, - +RootComponent?: React.ElementType, - +color?: string, - +size?: string, - +wrap?: boolean, - +muted?: boolean, -|}; - -class Foo extends React.Component { - render() { - return
; - } -} - -export default Foo; diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_14.js b/packages/react-docgen/tests/integration/__fixtures__/component_14.js deleted file mode 100644 index 05cae56cae5..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_14.js +++ /dev/null @@ -1,11 +0,0 @@ -type Props = $ReadOnly<{| - color?: ?string, -|}>; - -const ColoredView = React.forwardRef((props: Props, ref) => ( - -)); - -ColoredView.displayName = 'UncoloredView'; - -module.exports = ColoredView; \ No newline at end of file diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_15.js b/packages/react-docgen/tests/integration/__fixtures__/component_15.js deleted file mode 100644 index 8e18772b2d5..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_15.js +++ /dev/null @@ -1,25 +0,0 @@ -import type {Props as BarProps} from 'Bar.react'; - -const Bar = require('Bar.react'); - -type A = { other3: 'c' }; -type B = $Exact<{ other4: 'g' }>; -type C = $Exact<$ReadOnly<{ other5: 'f' }>>; - -type Props = {| - ...$Exact, - ...$Exact<$ReadOnly>, - ...BarProps3, - ...{ other: 'a' }, - ...$Exact<{ other2: 'b' }>, - ...A, - ...B, - ...C, - somePropOverride: 'baz', -|}; - -export default class Foo extends React.Component { - render() { - return ; - } -} \ No newline at end of file diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_16.js b/packages/react-docgen/tests/integration/__fixtures__/component_16.js deleted file mode 100644 index b06a5c2f23a..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_16.js +++ /dev/null @@ -1,16 +0,0 @@ -const propTypes = { - /** This does something. */ - bar: PropTypes.node, -}; - -export default function Foo(props) { - return
; -} - -Foo.propTypes = { - ...propTypes -}; - -Foo.defaultProps = { - bar: null, -}; \ No newline at end of file diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_17.js b/packages/react-docgen/tests/integration/__fixtures__/component_17.js deleted file mode 100644 index e37f0e2186e..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_17.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Testing descriptions of shape and oneOfType values - */ - -import React from 'react'; -import PropTypes from 'prop-types'; - -export default function Foo(props) { - return
; -} - -Foo.propTypes = { - shapeProp: PropTypes.shape({ - /** Comment for property a */ - a: PropTypes.string, - b: PropTypes.number - }), - exactProp: PropTypes.exact({ - /** Comment for property c */ - c: PropTypes.string, - d: PropTypes.number - }), - oneOfTypeProp: PropTypes.oneOfType([ - /** Comment for type string */ - PropTypes.string, - PropTypes.number - ]) -}; diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_18.js b/packages/react-docgen/tests/integration/__fixtures__/component_18.js deleted file mode 100644 index 397bc3c546e..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_18.js +++ /dev/null @@ -1,23 +0,0 @@ - -import React from 'react'; -import PropTypes from 'prop-types'; -import extendStyles from 'enhancers/extendStyles'; - -type Props = $ReadOnly<{| - color?: ?string, -|}>; - -const ColoredView = React.forwardRef((props: Props, ref) => ( -
-)); - -ColoredView.displayName = 'UncoloredView'; -ColoredView.propTypes = { - color: PropTypes.string.isRequired, - id: PropTypes.string -} -ColoredView.defaultProps = { - id: 'test-forward-ref-default' -} - -module.exports = extendStyles(ColoredView); diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_19.js b/packages/react-docgen/tests/integration/__fixtures__/component_19.js deleted file mode 100644 index 736ab4b50e4..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_19.js +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; - -type Props = {| - data?: Array, - ...React.ElementConfig, -|}; - -type State = {| - width: number, -|}; - -export default class Component extends React.PureComponent { - UNSAFE_componentWillReceiveProps(nextProps: Props) { - doSomething(); - } - - render() { - return ( -
Hello
- ); - } -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_2.js b/packages/react-docgen/tests/integration/__fixtures__/component_2.js deleted file mode 100644 index 677680e278c..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_2.js +++ /dev/null @@ -1,33 +0,0 @@ -import React from 'react'; - -export class Button extends React.Component { - static get displayName() { - return "button"; - } - - static get defaultProps() { - return { - type: "primary", - }; - } -} - -export function foo() { - return [].join(); -} - -export function chained() { - return foo.bar().join(); -} - -export function templateLiteral() { - return `foo bar`.split(' '); -} - -export function withThis() { - return this.foo(); -} - -export default function withNestedMemberExpressions() { - return this.blub.blob.foo(); -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_20.js b/packages/react-docgen/tests/integration/__fixtures__/component_20.js deleted file mode 100644 index 71876904f4b..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_20.js +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -const Button = () => ( -
-); - -Button.propTypes = { - /** This is a test */ - [children]: PropTypes.string.isRequired, -}; - -Button.defaultProps = { - [children]: "default", -}; - -export default Button; diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_21.tsx b/packages/react-docgen/tests/integration/__fixtures__/component_21.tsx deleted file mode 100644 index 6b0f73287e1..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_21.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React, { Component } from 'react'; - -type BaseProps = { - /** Optional prop */ - foo?: string, - /** Required prop */ - bar: number -}; - -type TransitionDuration = number | { enter?: number, exit?: number } | 'auto'; - -type Props = BaseProps & { - /** Complex union prop */ - baz: TransitionDuration -} - -/** - * This is a typescript class component - */ -export default class TSComponent extends Component { - render() { - return

Hello world

; - } -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_22.tsx b/packages/react-docgen/tests/integration/__fixtures__/component_22.tsx deleted file mode 100644 index dc09c4fb064..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_22.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; - -type Props = { - align?: "left" | "center" | "right" | "justify", - left?: boolean, - center?: boolean, - right?: boolean, - justify?: boolean, - /** - * position doc - */ - position: { - /** - * x coordinate doc - */ - x: number, - /** - * y coordinate doc - */ - y: number - } -}; - -/** - * This is a TypeScript function component - */ -export function TSFunctionComponent(props: Props) { - return

Hello world

; -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_23.tsx b/packages/react-docgen/tests/integration/__fixtures__/component_23.tsx deleted file mode 100644 index b7513378751..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_23.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React, { Component } from 'react'; - -interface BaseProps { - /** Optional prop */ - foo?: string, - /** Required prop */ - bar: number -} - -type TransitionDuration = number | { enter?: number, exit?: number } | 'auto'; - -interface Props extends BaseProps, OtherProps { - /** Complex union prop */ - baz: TransitionDuration -} - -/** - * This is a typescript class component - */ -export default class TSComponent extends Component { - render() { - return

Hello world

; - } -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_24.js b/packages/react-docgen/tests/integration/__fixtures__/component_24.js deleted file mode 100644 index 18df42b6037..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_24.js +++ /dev/null @@ -1,24 +0,0 @@ -import React, { Component } from 'react'; - -interface BaseProps { - /** Optional prop */ - foo?: string, - /** Required prop */ - bar: number -} - -type TransitionDuration = number | { enter?: number, exit?: number } | 'auto'; - -interface Props extends BaseProps, OtherProps { - /** Complex union prop */ - baz: TransitionDuration -} - -/** - * This is a flow class component with an interface as props - */ -export default class FlowComponent extends Component { - render() { - return

Hello world

; - } -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_25.tsx b/packages/react-docgen/tests/integration/__fixtures__/component_25.tsx deleted file mode 100644 index 55b2c8fa461..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_25.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React, { Component } from 'react'; - -type Test = Array; -interface BaseProps { - /** Optional prop */ - foo?: T, - /** Required prop */ - bar: Test -} - -interface Child {} - -interface Props extends BaseProps { - /** Complex union prop */ - baz: number -} - -/** - * This is a typescript class component - */ -export default class TSComponent extends Component { - render() { - return

Hello world

; - } -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_26.js b/packages/react-docgen/tests/integration/__fixtures__/component_26.js deleted file mode 100644 index 25c3387f3e8..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_26.js +++ /dev/null @@ -1,25 +0,0 @@ -import React, { Component } from 'react'; - -type Test = Array; -interface BaseProps { - /** Optional prop */ - foo?: T, - /** Required prop */ - bar: Test -} - -interface Child {} - -interface Props extends BaseProps { - /** Complex union prop */ - baz: number -} - -/** - * This is a typescript class component - */ -export default class FlowComponent extends Component { - render() { - return

Hello world

; - } -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_27.tsx b/packages/react-docgen/tests/integration/__fixtures__/component_27.tsx deleted file mode 100644 index 2b7ad0e8d30..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_27.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React, { Component } from 'react'; - -export interface Props { - foo: string -} - -/** - * This is a typescript class component - */ -export default class TSComponent extends Component { - render() { - return

Hello world

; - } - - /** - * This is a method - */ - foo(a: string): string { - return a; - } - - /** - * This is a public method - */ - public bar(a: string): string { - return a; - } - - /** - * This is a private method - */ - private baz(a: string): string { - return a; - } -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_28.tsx b/packages/react-docgen/tests/integration/__fixtures__/component_28.tsx deleted file mode 100644 index 28e4a56cbb1..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_28.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; - -interface Props { - /** - * Example prop description - */ - foo: boolean; -} - -/** - * Example component description - */ -const Component = React.forwardRef(({ foo = true }: Props, ref: any) => { - return
; -}) - -Component.displayName = 'ABC'; - -export default Component; diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_29.js b/packages/react-docgen/tests/integration/__fixtures__/component_29.js deleted file mode 100644 index 1dccffc1316..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_29.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from "react"; - -type Identity = T; - -type Props = { - prop: Identity, -} - -export default function MyComponent(props: Props) { - return
Hello World
-} diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_3.js b/packages/react-docgen/tests/integration/__fixtures__/component_3.js deleted file mode 100644 index d9e52938f96..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_3.js +++ /dev/null @@ -1,13 +0,0 @@ -import React, { PropTypes } from 'react'; -import extendStyles from 'enhancers/extendStyles'; - -const Test = props => -
- Hello world! -
; - -Test.propTypes = { - style: PropTypes.object, -}; - -export default extendStyles(Test); diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_30.js b/packages/react-docgen/tests/integration/__fixtures__/component_30.js deleted file mode 100644 index fe6dc6688fe..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_30.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from "react"; - -type Identity = T; - -type Props = { - prop: Identity, -} - -export default function MyComponent(props: Props) { - return
Hello World
-} diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_31.js b/packages/react-docgen/tests/integration/__fixtures__/component_31.js deleted file mode 100644 index d52f291f3ad..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_31.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from "react"; - -type Identity = T; - -type Props = { - prop: Identity>, -} - -export default function MyComponent(props: Props) { - return
Hello World
-} diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_32.js b/packages/react-docgen/tests/integration/__fixtures__/component_32.js deleted file mode 100644 index 209e4a4149d..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_32.js +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from "react"; - -type Props = { - segments: Array, -}; - -export default class Segments extends React.Component> { - render(): React.Node { - return null; - } - - foo(props: Props) {} -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_33.tsx b/packages/react-docgen/tests/integration/__fixtures__/component_33.tsx deleted file mode 100644 index c28397bfc11..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_33.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React, { Component } from 'react'; -import ExtendedProps from './component_39.jsx'; - -/** - * This is a typescript component with imported prop types - */ -export function ImportedExtendedComponent(props: ExtendedProps) { - return

Hello world

; -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_34.js b/packages/react-docgen/tests/integration/__fixtures__/component_34.js deleted file mode 100644 index 0001bf8c641..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_34.js +++ /dev/null @@ -1,13 +0,0 @@ -import Button from './component_6.js'; -import PropTypes from 'prop-types'; - -export function CustomButton({color, ...otherProps}) { - return -); - -Button.propTypes = { - children: React.PropTypes.string.isRequired, - onClick: React.PropTypes.func, - style: React.PropTypes.object, -}; - -Button.childContextTypes = { - color: React.PropTypes.string, -}; - -Button.contextTypes = { - config: React.PropTypes.object, -}; - -export default Button; diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_6.js b/packages/react-docgen/tests/integration/__fixtures__/component_6.js deleted file mode 100644 index 89355ab5f45..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_6.js +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -const Button = ({ children, onClick, style = {} }) => ( - -); - -Button.propTypes = { - children: PropTypes.string.isRequired, - onClick: PropTypes.func, - style: PropTypes.object, -}; - -Button.childContextTypes = { - color: PropTypes.string, -}; - -Button.contextTypes = { - config: PropTypes.object, -}; -export default Button; diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_7.js b/packages/react-docgen/tests/integration/__fixtures__/component_7.js deleted file mode 100644 index b0207d536de..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_7.js +++ /dev/null @@ -1,12 +0,0 @@ -var Component, createReactClass; - -createReactClass = require('create-react-class'); - -/** - * The is a component to test the document generation - */ -Component = createReactClass({ - displayName: 'Component', -}); - -module.exports = Component; diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_8.js b/packages/react-docgen/tests/integration/__fixtures__/component_8.js deleted file mode 100644 index 097c3d0eff3..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_8.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Testing array parameter destructuring. - */ - -import React from 'react'; - -var pt = React.PropTypes; - -class Parent extends React.Component { - onChangeSlider([min, max]) { - this.setState({ min, max }); - } -} - -export default Parent; diff --git a/packages/react-docgen/tests/integration/__fixtures__/component_9.js b/packages/react-docgen/tests/integration/__fixtures__/component_9.js deleted file mode 100644 index f1ce9c6b7c1..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/component_9.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Testing render method as public class field. - */ -import view from "./view.jsx"; -/** - * Should be recognized as component. - */ -export default class ExampleComponent extends SomeOtherComponent { - render = view; -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/flow-export-type.js b/packages/react-docgen/tests/integration/__fixtures__/flow-export-type.js deleted file mode 100644 index ad227ba6897..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/flow-export-type.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @flow - */ - -import React, { Component } from 'react'; - -export type Props = { - foo: string -} - -/** - * This is a Flow class component - */ -export default class FlowComponent extends Component { - render() { - return

Hello world

; - } - - foo(a: string): string { - return a; - } - - bar(a: string): string { - return a; - } -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/flow-import-type.js b/packages/react-docgen/tests/integration/__fixtures__/flow-import-type.js deleted file mode 100644 index c5a4dfec45e..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/flow-import-type.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @flow - */ - -import React, { Component } from 'react'; -import type { Props as ImportedProps } from './flow-export-type.js'; - -export type ExtendedProps = { - ...ImportedProps, - bar: number -} - -/** - * This is a Flow component with imported prop types - */ -export function ImportedComponent(props: ImportedProps) { - return

Hello world

; -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/flow-spread-import-type.js b/packages/react-docgen/tests/integration/__fixtures__/flow-spread-import-type.js deleted file mode 100644 index d7917c8d926..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/flow-spread-import-type.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @flow - */ - -import React, { Component } from 'react'; -import type {ExtendedProps} from './flow-import-type.js'; - -/** - * This is a Flow component with imported prop types - */ -export function ImportedExtendedComponent(props: ExtendedProps) { - return

Hello world

; -} diff --git a/packages/react-docgen/tests/integration/__fixtures__/namespace-export.tsx b/packages/react-docgen/tests/integration/__fixtures__/namespace-export.tsx deleted file mode 100644 index 6757aeb2ac5..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/namespace-export.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import * as React from 'react'; - -interface IProps { - value: string; -} - -export default class extends React.Component { - render() { - return
; - } -} - -export * as namespace from "./support/other-exports.js"; diff --git a/packages/react-docgen/tests/integration/__fixtures__/support/other-exports.ts b/packages/react-docgen/tests/integration/__fixtures__/support/other-exports.ts deleted file mode 100644 index 129c265f93d..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/support/other-exports.ts +++ /dev/null @@ -1 +0,0 @@ -export default 'otherstring' diff --git a/packages/react-docgen/tests/integration/__fixtures__/support/some-exports.ts b/packages/react-docgen/tests/integration/__fixtures__/support/some-exports.ts deleted file mode 100644 index 75178b1edae..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/support/some-exports.ts +++ /dev/null @@ -1,5 +0,0 @@ -const obj = { objDestruct: "string" }; - -export const { objDestruct } = obj; - -export defaultFrom from './other-exports.js'; diff --git a/packages/react-docgen/tests/integration/__fixtures__/test-all-imports.tsx b/packages/react-docgen/tests/integration/__fixtures__/test-all-imports.tsx deleted file mode 100644 index a2686d0f6cf..00000000000 --- a/packages/react-docgen/tests/integration/__fixtures__/test-all-imports.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import { objDestruct, defaultFrom } from './support/some-exports.js'; - -/** - * This is a TS component with imported stuff - */ -export function ImportedExtendedComponent({ x = objDestruct, y = defaultFrom }) { - return

Hello world

; -} diff --git a/packages/react-docgen/tests/integration/__snapshots__/integration-test.ts.snap b/packages/react-docgen/tests/integration/__snapshots__/integration-test.ts.snap deleted file mode 100644 index 9e4ece0c25a..00000000000 --- a/packages/react-docgen/tests/integration/__snapshots__/integration-test.ts.snap +++ /dev/null @@ -1,2165 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`integration > fixtures > processes component "class-without-id.tsx" without errors 1`] = ` -[ - { - "description": "", - "methods": [], - "props": { - "value": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_1.js" without errors 1`] = ` -[ - { - "description": "The is a component to test the document generation", - "displayName": "Component", - "methods": [], - }, -] -`; - -exports[`integration > fixtures > processes component "component_2.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "button", - "methods": [ - { - "docblock": null, - "modifiers": [ - "static", - "get", - ], - "name": "displayName", - "params": [], - "returns": null, - }, - { - "docblock": null, - "modifiers": [ - "static", - "get", - ], - "name": "defaultProps", - "params": [], - "returns": null, - }, - ], - "props": { - "type": { - "defaultValue": { - "computed": false, - "value": ""primary"", - }, - "required": false, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_3.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "Test", - "methods": [], - "props": { - "style": { - "description": "", - "required": false, - "type": { - "name": "object", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_4.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "Parent", - "methods": [], - "props": { - "child": { - "description": "", - "required": true, - "type": { - "computed": true, - "name": "shape", - "value": "Child.propTypes", - }, - }, - "childExact": { - "description": "", - "required": true, - "type": { - "computed": true, - "name": "exact", - "value": "Child.propTypes", - }, - }, - "extendedChild": { - "description": "", - "required": true, - "type": { - "name": "shape", - "value": { - "adopted": { - "name": "bool", - "required": true, - }, - }, - }, - }, - "extendedChildExact": { - "description": "", - "required": true, - "type": { - "name": "exact", - "value": { - "adopted": { - "name": "bool", - "required": true, - }, - }, - }, - }, - "something": { - "description": "", - "required": true, - "type": { - "name": "string", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_5.js" without errors 1`] = ` -[ - { - "childContext": { - "color": { - "required": false, - "type": { - "name": "string", - }, - }, - }, - "context": { - "config": { - "required": false, - "type": { - "name": "object", - }, - }, - }, - "description": "", - "displayName": "Button", - "methods": [], - "props": { - "children": { - "description": "", - "required": true, - "type": { - "name": "string", - }, - }, - "onClick": { - "description": "", - "required": false, - "type": { - "name": "func", - }, - }, - "style": { - "defaultValue": { - "computed": false, - "value": "{}", - }, - "description": "", - "required": false, - "type": { - "name": "object", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_6.js" without errors 1`] = ` -[ - { - "childContext": { - "color": { - "required": false, - "type": { - "name": "string", - }, - }, - }, - "context": { - "config": { - "required": false, - "type": { - "name": "object", - }, - }, - }, - "description": "", - "displayName": "Button", - "methods": [], - "props": { - "children": { - "description": "", - "required": true, - "type": { - "name": "string", - }, - }, - "onClick": { - "description": "", - "required": false, - "type": { - "name": "func", - }, - }, - "style": { - "defaultValue": { - "computed": false, - "value": "{}", - }, - "description": "", - "required": false, - "type": { - "name": "object", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_7.js" without errors 1`] = ` -[ - { - "description": "The is a component to test the document generation", - "displayName": "Component", - "methods": [], - }, -] -`; - -exports[`integration > fixtures > processes component "component_8.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "Parent", - "methods": [ - { - "docblock": null, - "modifiers": [], - "name": "onChangeSlider", - "params": [ - { - "name": "[min, max]", - "optional": false, - "type": null, - }, - ], - "returns": null, - }, - ], - }, -] -`; - -exports[`integration > fixtures > processes component "component_9.js" without errors 1`] = ` -[ - { - "description": "Should be recognized as component.", - "displayName": "ExampleComponent", - "methods": [], - }, -] -`; - -exports[`integration > fixtures > processes component "component_10.js" without errors 1`] = ` -[ - { - "description": "React component that display current time at current location.", - "displayName": "Clock", - "methods": [ - { - "description": "Update clock state with new time", - "docblock": "Update clock state with new time", - "modifiers": [], - "name": "updateClock", - "params": [], - "returns": null, - }, - { - "description": "Parse current Date object", - "docblock": "Parse current Date object - -@returns {Object} currentTime - @returns {int} currentTime.hour - @returns {int} currentTime.minutes - @returns {string} currentTime.ampm "am" or "pm" - @returns {string} currentTime.dayOfWeek - @returns {string} currentTime.month - @returns {int} currentTime.date", - "modifiers": [], - "name": "getTime", - "params": [], - "returns": { - "description": "currentTime", - "type": { - "name": "Object", - }, - }, - }, - { - "description": "Update current clock for every 1 second", - "docblock": "Update current clock for every 1 second", - "modifiers": [], - "name": "setTimer", - "params": [], - "returns": null, - }, - ], - "props": { - "title": { - "description": "A text display current's user identity, - "Nobody" if no one is detected in the background, - "Hi, ..name" if an user is detected", - "required": false, - "type": { - "name": "string", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_11.js" without errors 1`] = ` -[ - { - "composes": [ - "OtherProps", - ], - "description": "", - "displayName": "MyComponent", - "methods": [], - "props": { - "fooProp": { - "description": "fooProp is spread in from a locally resolved type", - "flowType": { - "name": "string", - }, - "required": false, - }, - "prop1": { - "description": "The first prop", - "flowType": { - "name": "string", - }, - "required": true, - }, - "prop2": { - "description": "The second, covariant prop", - "flowType": { - "name": "number", - }, - "required": true, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_12.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "Paper", - "methods": [], - "props": { - "anchorOrigin": { - "defaultValue": { - "computed": false, - "value": "{ - vertical: 'top', - horizontal: 'left', -}", - }, - "description": "This is the point on the anchor where the popover's -\`anchorEl\` will attach to. This is not used when the -anchorReference is 'anchorPosition'. - -Options: -vertical: [top, center, bottom]; -horizontal: [left, center, right].", - "flowType": { - "name": "signature", - "raw": "{ - horizontal: 'left' | 'center' | 'right' | number, - vertical: 'top' | 'center' | 'bottom' | number, -}", - "signature": { - "properties": [ - { - "key": "horizontal", - "value": { - "elements": [ - { - "name": "literal", - "value": "'left'", - }, - { - "name": "literal", - "value": "'center'", - }, - { - "name": "literal", - "value": "'right'", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "'left' | 'center' | 'right' | number", - "required": true, - }, - }, - { - "key": "vertical", - "value": { - "elements": [ - { - "name": "literal", - "value": "'top'", - }, - { - "name": "literal", - "value": "'center'", - }, - { - "name": "literal", - "value": "'bottom'", - }, - { - "name": "number", - }, - ], - "name": "union", - "raw": "'top' | 'center' | 'bottom' | number", - "required": true, - }, - }, - ], - }, - "type": "object", - }, - "required": false, - }, - "children": { - "description": "@ignore", - "flowType": { - "name": "Node", - }, - "required": false, - }, - "classes": { - "description": "Useful to extend the style applied to components.", - "flowType": { - "name": "Object", - }, - "required": false, - }, - "component": { - "defaultValue": { - "computed": false, - "value": "'div'", - }, - "description": "The component used for the root node. -This currently has to be flow cast in defaultProps as of flow 0.59.0", - "flowType": { - "name": "ElementType", - }, - "required": false, - }, - "elevation": { - "defaultValue": { - "computed": false, - "value": "2", - }, - "description": "Shadow depth, corresponds to \`dp\` in the spec. -It's accepting values between 0 and 24 inclusive.", - "flowType": { - "name": "number", - }, - "required": false, - }, - "labelRowsPerPage": { - "defaultValue": { - "computed": false, - "value": "'Rows per page:'", - }, - "description": "Useful to customize the rows per page label. Invoked with a \`{ from, to, count, page }\` -object.", - "flowType": { - "name": "Node", - }, - "required": false, - }, - "timeout": { - "defaultValue": { - "computed": false, - "value": "300", - }, - "description": "The duration for the transition, in milliseconds. -You may specify a single timeout for all transitions, or individually with an object. - -Set to 'auto' to automatically calculate transition time based on height.", - "flowType": { - "elements": [ - { - "name": "number", - }, - { - "name": "signature", - "raw": "{ enter?: number, exit?: number }", - "signature": { - "properties": [ - { - "key": "enter", - "value": { - "name": "number", - "required": false, - }, - }, - { - "key": "exit", - "value": { - "name": "number", - "required": false, - }, - }, - ], - }, - "type": "object", - }, - { - "name": "literal", - "value": "'auto'", - }, - ], - "name": "union", - "raw": "number | { enter?: number, exit?: number } | 'auto'", - }, - "required": false, - }, - "transition": { - "description": "Transition component.", - "flowType": { - "elements": [ - { - "name": "unknown", - }, - ], - "name": "ComponentType", - "raw": "ComponentType<*>", - }, - "required": true, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_13.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "Foo", - "methods": [], - "props": { - "RootComponent": { - "description": "", - "flowType": { - "name": "ReactElementType", - "raw": "React.ElementType", - }, - "required": false, - }, - "align": { - "description": "", - "flowType": { - "elements": [ - { - "name": "literal", - "value": ""left"", - }, - { - "name": "literal", - "value": ""center"", - }, - { - "name": "literal", - "value": ""right"", - }, - { - "name": "literal", - "value": ""justify"", - }, - ], - "name": "union", - "raw": ""left" | "center" | "right" | "justify"", - }, - "required": false, - }, - "capitalize": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - "center": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - "children": { - "description": "", - "flowType": { - "name": "ReactNode", - "raw": "React.Node", - }, - "required": false, - }, - "className": { - "description": "", - "flowType": { - "name": "string", - }, - "required": false, - }, - "color": { - "description": "", - "flowType": { - "name": "string", - }, - "required": false, - }, - "justify": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - "leading": { - "description": "", - "flowType": { - "elements": [ - { - "name": "literal", - "value": ""none"", - }, - { - "name": "literal", - "value": ""tight"", - }, - { - "name": "literal", - "value": ""normal"", - }, - { - "name": "literal", - "value": ""loose"", - }, - ], - "name": "union", - "raw": ""none" | "tight" | "normal" | "loose"", - }, - "required": false, - }, - "leadingLoose": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - "leadingNone": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - "leadingNormal": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - "leadingTight": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - "left": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - "lowercase": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - "muted": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - "right": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - "size": { - "description": "", - "flowType": { - "name": "string", - }, - "required": false, - }, - "tracking": { - "description": "", - "flowType": { - "elements": [ - { - "name": "literal", - "value": ""tight"", - }, - { - "name": "literal", - "value": ""normal"", - }, - { - "name": "literal", - "value": ""wide"", - }, - ], - "name": "union", - "raw": ""tight" | "normal" | "wide"", - }, - "required": false, - }, - "trackingNormal": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - "trackingTight": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - "trackingWide": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - "transform": { - "description": "", - "flowType": { - "elements": [ - { - "name": "literal", - "value": ""lowercase"", - }, - { - "name": "literal", - "value": ""uppercase"", - }, - { - "name": "literal", - "value": ""capitalize"", - }, - ], - "name": "union", - "raw": ""lowercase" | "uppercase" | "capitalize"", - }, - "required": false, - }, - "uppercase": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - "wrap": { - "description": "", - "flowType": { - "name": "boolean", - }, - "required": false, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_14.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "UncoloredView", - "methods": [], - "props": { - "color": { - "description": "", - "flowType": { - "name": "string", - "nullable": true, - }, - "required": false, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_15.js" without errors 1`] = ` -[ - { - "composes": [ - "BarProps", - "BarProps2", - "BarProps3", - ], - "description": "", - "displayName": "Foo", - "methods": [], - "props": { - "other": { - "description": "", - "flowType": { - "name": "literal", - "value": "'a'", - }, - "required": true, - }, - "other2": { - "description": "", - "flowType": { - "name": "literal", - "value": "'b'", - }, - "required": true, - }, - "other3": { - "description": "", - "flowType": { - "name": "literal", - "value": "'c'", - }, - "required": true, - }, - "other4": { - "description": "", - "flowType": { - "name": "literal", - "value": "'g'", - }, - "required": true, - }, - "other5": { - "description": "", - "flowType": { - "name": "literal", - "value": "'f'", - }, - "required": true, - }, - "somePropOverride": { - "description": "", - "flowType": { - "name": "literal", - "value": "'baz'", - }, - "required": true, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_16.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "Foo", - "methods": [], - "props": { - "bar": { - "defaultValue": { - "computed": false, - "value": "null", - }, - "description": "This does something.", - "required": false, - "type": { - "name": "custom", - "raw": "PropTypes.node", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_17.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "Foo", - "methods": [], - "props": { - "exactProp": { - "description": "", - "required": false, - "type": { - "name": "exact", - "value": { - "c": { - "description": "Comment for property c", - "name": "string", - "required": false, - }, - "d": { - "name": "number", - "required": false, - }, - }, - }, - }, - "oneOfTypeProp": { - "description": "", - "required": false, - "type": { - "name": "union", - "value": [ - { - "description": "Comment for type string", - "name": "string", - }, - { - "name": "number", - }, - ], - }, - }, - "shapeProp": { - "description": "", - "required": false, - "type": { - "name": "shape", - "value": { - "a": { - "description": "Comment for property a", - "name": "string", - "required": false, - }, - "b": { - "name": "number", - "required": false, - }, - }, - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_18.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "UncoloredView", - "methods": [], - "props": { - "color": { - "description": "", - "flowType": { - "name": "string", - "nullable": true, - }, - "required": false, - "type": { - "name": "string", - }, - }, - "id": { - "defaultValue": { - "computed": false, - "value": "'test-forward-ref-default'", - }, - "description": "", - "required": false, - "type": { - "name": "string", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_19.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "Component", - "methods": [], - "props": { - "data": { - "description": "", - "flowType": { - "elements": [ - { - "name": "mixed", - }, - ], - "name": "Array", - "raw": "Array", - }, - "required": false, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_20.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "Button", - "methods": [], - "props": { - "@computed#children": { - "defaultValue": { - "computed": false, - "value": ""default"", - }, - "description": "This is a test", - "required": false, - "type": { - "name": "string", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_21.tsx" without errors 1`] = ` -[ - { - "description": "This is a typescript class component", - "displayName": "TSComponent", - "methods": [], - "props": { - "bar": { - "description": "Required prop", - "required": true, - "tsType": { - "name": "number", - }, - }, - "baz": { - "description": "Complex union prop", - "required": true, - "tsType": { - "elements": [ - { - "name": "number", - }, - { - "name": "signature", - "raw": "{ enter?: number, exit?: number }", - "signature": { - "properties": [ - { - "key": "enter", - "value": { - "name": "number", - "required": false, - }, - }, - { - "key": "exit", - "value": { - "name": "number", - "required": false, - }, - }, - ], - }, - "type": "object", - }, - { - "name": "literal", - "value": "'auto'", - }, - ], - "name": "union", - "raw": "number | { enter?: number, exit?: number } | 'auto'", - }, - }, - "foo": { - "description": "Optional prop", - "required": false, - "tsType": { - "name": "string", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_22.tsx" without errors 1`] = ` -[ - { - "description": "This is a TypeScript function component", - "displayName": "TSFunctionComponent", - "methods": [], - "props": { - "align": { - "description": "", - "required": false, - "tsType": { - "elements": [ - { - "name": "literal", - "value": ""left"", - }, - { - "name": "literal", - "value": ""center"", - }, - { - "name": "literal", - "value": ""right"", - }, - { - "name": "literal", - "value": ""justify"", - }, - ], - "name": "union", - "raw": ""left" | "center" | "right" | "justify"", - }, - }, - "center": { - "description": "", - "required": false, - "tsType": { - "name": "boolean", - }, - }, - "justify": { - "description": "", - "required": false, - "tsType": { - "name": "boolean", - }, - }, - "left": { - "description": "", - "required": false, - "tsType": { - "name": "boolean", - }, - }, - "position": { - "description": "position doc", - "required": true, - "tsType": { - "name": "signature", - "raw": "{ - /** - * x coordinate doc - */ - x: number, - /** - * y coordinate doc - */ - y: number -}", - "signature": { - "properties": [ - { - "description": "x coordinate doc", - "key": "x", - "value": { - "name": "number", - "required": true, - }, - }, - { - "description": "y coordinate doc", - "key": "y", - "value": { - "name": "number", - "required": true, - }, - }, - ], - }, - "type": "object", - }, - }, - "right": { - "description": "", - "required": false, - "tsType": { - "name": "boolean", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_23.tsx" without errors 1`] = ` -[ - { - "composes": [ - "OtherProps", - ], - "description": "This is a typescript class component", - "displayName": "TSComponent", - "methods": [], - "props": { - "bar": { - "description": "Required prop", - "required": true, - "tsType": { - "name": "number", - }, - }, - "baz": { - "description": "Complex union prop", - "required": true, - "tsType": { - "elements": [ - { - "name": "number", - }, - { - "name": "signature", - "raw": "{ enter?: number, exit?: number }", - "signature": { - "properties": [ - { - "key": "enter", - "value": { - "name": "number", - "required": false, - }, - }, - { - "key": "exit", - "value": { - "name": "number", - "required": false, - }, - }, - ], - }, - "type": "object", - }, - { - "name": "literal", - "value": "'auto'", - }, - ], - "name": "union", - "raw": "number | { enter?: number, exit?: number } | 'auto'", - }, - }, - "foo": { - "description": "Optional prop", - "required": false, - "tsType": { - "name": "string", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_24.js" without errors 1`] = ` -[ - { - "composes": [ - "OtherProps", - ], - "description": "This is a flow class component with an interface as props", - "displayName": "FlowComponent", - "methods": [], - "props": { - "bar": { - "description": "Required prop", - "flowType": { - "name": "number", - }, - "required": true, - }, - "baz": { - "description": "Complex union prop", - "flowType": { - "elements": [ - { - "name": "number", - }, - { - "name": "signature", - "raw": "{ enter?: number, exit?: number }", - "signature": { - "properties": [ - { - "key": "enter", - "value": { - "name": "number", - "required": false, - }, - }, - { - "key": "exit", - "value": { - "name": "number", - "required": false, - }, - }, - ], - }, - "type": "object", - }, - { - "name": "literal", - "value": "'auto'", - }, - ], - "name": "union", - "raw": "number | { enter?: number, exit?: number } | 'auto'", - }, - "required": true, - }, - "foo": { - "description": "Optional prop", - "flowType": { - "name": "string", - }, - "required": false, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_25.tsx" without errors 1`] = ` -[ - { - "description": "This is a typescript class component", - "displayName": "TSComponent", - "methods": [], - "props": { - "bar": { - "description": "Required prop", - "required": true, - "tsType": { - "elements": [ - { - "name": "Child", - }, - ], - "name": "Array", - "raw": "Array", - }, - }, - "baz": { - "description": "Complex union prop", - "required": true, - "tsType": { - "name": "number", - }, - }, - "foo": { - "description": "Optional prop", - "required": false, - "tsType": { - "name": "Child", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_26.js" without errors 1`] = ` -[ - { - "description": "This is a typescript class component", - "displayName": "FlowComponent", - "methods": [], - "props": { - "bar": { - "description": "Required prop", - "flowType": { - "elements": [ - { - "name": "Child", - }, - ], - "name": "Array", - "raw": "Array", - }, - "required": true, - }, - "baz": { - "description": "Complex union prop", - "flowType": { - "name": "number", - }, - "required": true, - }, - "foo": { - "description": "Optional prop", - "flowType": { - "name": "Child", - }, - "required": false, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_27.tsx" without errors 1`] = ` -[ - { - "description": "This is a typescript class component", - "displayName": "TSComponent", - "methods": [ - { - "description": "This is a method", - "docblock": "This is a method", - "modifiers": [], - "name": "foo", - "params": [ - { - "name": "a", - "optional": false, - "type": { - "name": "string", - }, - }, - ], - "returns": { - "type": { - "name": "string", - }, - }, - }, - { - "description": "This is a public method", - "docblock": "This is a public method", - "modifiers": [], - "name": "bar", - "params": [ - { - "name": "a", - "optional": false, - "type": { - "name": "string", - }, - }, - ], - "returns": { - "type": { - "name": "string", - }, - }, - }, - ], - "props": { - "foo": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_28.tsx" without errors 1`] = ` -[ - { - "description": "Example component description", - "displayName": "ABC", - "methods": [], - "props": { - "foo": { - "defaultValue": { - "computed": false, - "value": "true", - }, - "description": "Example prop description", - "required": false, - "tsType": { - "name": "boolean", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_29.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "MyComponent", - "methods": [], - "props": { - "prop": { - "description": "", - "flowType": { - "name": "T", - }, - "required": true, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_30.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "MyComponent", - "methods": [], - "props": { - "prop": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_31.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "MyComponent", - "methods": [], - "props": { - "prop": { - "description": "", - "flowType": { - "name": "T", - }, - "required": true, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_32.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "Segments", - "methods": [ - { - "docblock": null, - "modifiers": [], - "name": "foo", - "params": [ - { - "name": "props", - "optional": false, - "type": { - "alias": "Props", - "name": "signature", - "raw": "{ - segments: Array, -}", - "signature": { - "properties": [ - { - "key": "segments", - "value": { - "elements": [ - { - "name": "T", - }, - ], - "name": "Array", - "raw": "Array", - "required": true, - }, - }, - ], - }, - "type": "object", - }, - }, - ], - "returns": null, - }, - ], - "props": { - "segments": { - "description": "", - "flowType": { - "elements": [ - { - "name": "T", - }, - ], - "name": "Array", - "raw": "Array", - }, - "required": true, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_33.tsx" without errors 1`] = ` -[ - { - "description": "This is a typescript component with imported prop types", - "displayName": "ImportedExtendedComponent", - "methods": [], - "props": { - "bar": { - "description": "", - "required": true, - "tsType": { - "name": "number", - }, - }, - "foo": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_34.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "CustomButton", - "methods": [], - "props": { - "children": { - "description": "", - "required": true, - "type": { - "name": "string", - }, - }, - "color": { - "description": "", - "required": false, - "type": { - "name": "string", - }, - }, - "onClick": { - "description": "", - "required": false, - "type": { - "name": "func", - }, - }, - "style": { - "description": "", - "required": false, - "type": { - "name": "object", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_35.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "SuperCustomButton", - "methods": [], - "props": { - "children": { - "description": "", - "required": true, - "type": { - "name": "string", - }, - }, - "onClick": { - "description": "", - "required": false, - "type": { - "name": "func", - }, - }, - "style": { - "description": "", - "required": false, - "type": { - "name": "object", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_36.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "SuperDuperCustomButton", - "methods": [], - "props": { - "children": { - "description": "", - "required": true, - "type": { - "name": "string", - }, - }, - "onClick": { - "description": "", - "required": false, - "type": { - "name": "func", - }, - }, - "style": { - "description": "", - "required": false, - "type": { - "name": "object", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_37.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "SuperDuperCustomButton", - "methods": [], - "props": { - "children": { - "description": "", - "required": true, - "type": { - "name": "string", - }, - }, - "onClick": { - "description": "", - "required": false, - "type": { - "name": "func", - }, - }, - "style": { - "description": "", - "required": false, - "type": { - "name": "object", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_38.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "SuperDuperCustomButton", - "methods": [], - "props": { - "children": { - "description": "", - "required": true, - "type": { - "name": "string", - }, - }, - "onClick": { - "description": "", - "required": false, - "type": { - "name": "func", - }, - }, - "style": { - "description": "", - "required": false, - "type": { - "name": "object", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_39.tsx" without errors 1`] = ` -[ - { - "description": "This is a typescript component with imported prop types", - "displayName": "ImportedComponent", - "methods": [], - "props": { - "foo": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_40.js" without errors 1`] = ` -[ - { - "description": "", - "displayName": "SuperDuperCustomButton", - "methods": [], - "props": { - "size": { - "defaultValue": { - "computed": true, - "value": "Sizes.EXTRA_LARGE", - }, - "description": "", - "required": false, - "type": { - "computed": true, - "name": "enum", - "value": "Object.values(Sizes)", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_41.tsx" without errors 1`] = ` -[ - { - "description": "", - "displayName": "MyComponent", - "methods": [], - "props": { - "value": { - "description": "String value of a number", - "required": false, - "tsType": { - "name": "STRING_VALS[number]", - "raw": "typeof STRING_VALS[number]", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_42.js" without errors 1`] = ` -[ - { - "description": "", - "methods": [], - "props": { - "foo": { - "defaultValue": { - "computed": false, - "value": "'bar'", - }, - "required": false, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "component_43.tsx" without errors 1`] = ` -[ - { - "description": "", - "displayName": "MenuItem", - "methods": [], - "props": { - "children": { - "description": "Menu item contents.", - "required": false, - "type": { - "name": "node", - }, - }, - "classes": { - "description": "Override or extend the styles applied to the component. See CSS API below for more details.", - "required": false, - "type": { - "name": "object", - }, - }, - "component": { - "defaultValue": { - "computed": false, - "value": "'li'", - }, - "required": false, - }, - "disableGutters": { - "defaultValue": { - "computed": false, - "value": "false", - }, - "required": false, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "flow-export-type.js" without errors 1`] = ` -[ - { - "description": "This is a Flow class component", - "displayName": "FlowComponent", - "methods": [ - { - "docblock": null, - "modifiers": [], - "name": "foo", - "params": [ - { - "name": "a", - "optional": false, - "type": { - "name": "string", - }, - }, - ], - "returns": { - "type": { - "name": "string", - }, - }, - }, - { - "docblock": null, - "modifiers": [], - "name": "bar", - "params": [ - { - "name": "a", - "optional": false, - "type": { - "name": "string", - }, - }, - ], - "returns": { - "type": { - "name": "string", - }, - }, - }, - ], - "props": { - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "flow-import-type.js" without errors 1`] = ` -[ - { - "description": "This is a Flow component with imported prop types", - "displayName": "ImportedComponent", - "methods": [], - "props": { - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "flow-spread-import-type.js" without errors 1`] = ` -[ - { - "description": "This is a Flow component with imported prop types", - "displayName": "ImportedExtendedComponent", - "methods": [], - "props": { - "bar": { - "description": "", - "flowType": { - "name": "number", - }, - "required": true, - }, - "foo": { - "description": "", - "flowType": { - "name": "string", - }, - "required": true, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "namespace-export.tsx" without errors 1`] = ` -[ - { - "description": "", - "methods": [], - "props": { - "value": { - "description": "", - "required": true, - "tsType": { - "name": "string", - }, - }, - }, - }, -] -`; - -exports[`integration > fixtures > processes component "test-all-imports.tsx" without errors 1`] = ` -[ - { - "description": "This is a TS component with imported stuff", - "displayName": "ImportedExtendedComponent", - "methods": [], - "props": { - "x": { - "defaultValue": { - "computed": false, - "value": ""string"", - }, - "required": false, - }, - "y": { - "defaultValue": { - "computed": false, - "value": "'otherstring'", - }, - "required": false, - }, - }, - }, -] -`; diff --git a/packages/react-docgen/tests/integration/integration-test.ts b/packages/react-docgen/tests/integration/integration-test.ts deleted file mode 100644 index b05f87545e3..00000000000 --- a/packages/react-docgen/tests/integration/integration-test.ts +++ /dev/null @@ -1,40 +0,0 @@ -import fs from 'fs'; -import { dirname, join } from 'path'; -import { describe, expect, test } from 'vitest'; -import { parse, makeFsImporter } from '../../src/main'; -import { fileURLToPath } from 'url'; - -describe('integration', () => { - describe('fixtures', () => { - const fixturePath = join( - dirname(fileURLToPath(import.meta.url)), - '__fixtures__', - ); - const fileNames = fs.readdirSync(fixturePath, { withFileTypes: true }); - - for (const entry of fileNames) { - if (entry.isDirectory()) { - continue; - } - const name = entry.name; - - const filePath = join(fixturePath, name); - const fileContent = fs.readFileSync(filePath, 'utf8'); - - test(`processes component "${name}" without errors`, () => { - let result; - - expect(() => { - result = parse(fileContent, { - importer: makeFsImporter(), - babelOptions: { - filename: filePath, - babelrc: false, - }, - }); - }).not.toThrowError(); - expect(result).toMatchSnapshot(); - }); - } - }); -}); diff --git a/packages/react-docgen/tests/setupTestFramework.ts b/packages/react-docgen/tests/setupTestFramework.ts deleted file mode 100644 index a667973cb46..00000000000 --- a/packages/react-docgen/tests/setupTestFramework.ts +++ /dev/null @@ -1,4 +0,0 @@ -import NodePathSerializer from './NodePathSerializer.js'; -import { expect } from 'vitest'; - -expect.addSnapshotSerializer(NodePathSerializer); diff --git a/packages/react-docgen/tests/utils.ts b/packages/react-docgen/tests/utils.ts deleted file mode 100644 index 9ac4391c1a7..00000000000 --- a/packages/react-docgen/tests/utils.ts +++ /dev/null @@ -1,273 +0,0 @@ -import type { TransformOptions } from '@babel/core'; -import type { NodePath } from '@babel/traverse'; -import type { Importer, ImportPath } from '../src/importer/index.js'; -import FileState from '../src/FileState.js'; -import babelParse from '../src/babelParser.js'; -import type { - ExportDefaultDeclaration, - Expression, - ExpressionStatement, - Program, - Statement, -} from '@babel/types'; -import { afterEach } from 'vitest'; - -interface ParseCall { - (code: string, importer: Importer): NodePath; - // eslint-disable-next-line @typescript-eslint/unified-signatures - (code: string, options: TransformOptions): NodePath; - ( - code: string, - options?: TransformOptions, - importer?: Importer, - returnFileState?: B, - ): B extends true ? FileState : NodePath; -} - -interface Parse extends ParseCall { - expression( - src: string, - options?: TransformOptions, - ): NodePath; - expression( - src: string, - importer: Importer, - options?: TransformOptions, - ): NodePath; - statement(src: string, index?: number): NodePath; - statement( - src: string, - importer: Importer, - index?: number, - ): NodePath; - statement( - src: string, - // eslint-disable-next-line @typescript-eslint/unified-signatures - options: TransformOptions, - index?: number, - ): NodePath; - statement( - src: string, - importer: Importer, - options: TransformOptions, - index?: number, - ): NodePath; - expressionLast( - src: string, - options?: TransformOptions, - ): NodePath; - expressionLast( - src: string, - importer: Importer, - options?: TransformOptions, - ): NodePath; - statementLast( - src: string, - options?: TransformOptions, - ): NodePath; - statementLast( - src: string, - importer: Importer, - options?: TransformOptions, - ): NodePath; -} - -function parseDefault( - code: string, - options: Importer | TransformOptions, - importer: Importer, - returnFileState: true, -): FileState; -function parseDefault( - code: string, - options: Importer | TransformOptions, - importer: Importer, - returnFileState: false, -): NodePath; -/** - * Returns a NodePath to the program path of the passed node - * Parses JS and Flow - */ -function parseDefault( - code: string, - options: Importer | TransformOptions = {}, - importer: Importer = noopImporter, - returnFileState = false, -): FileState | NodePath { - if (typeof options !== 'object') { - importer = options; - options = {}; - } - const opts = { - babelrc: false, - ...options, - }; - const ast = babelParse(code, opts); - const fileState = new FileState(opts, { - ast, - code, - importer, - }); - - if (returnFileState) { - return fileState; - } - - return fileState.path; -} - -const parseTS: ParseCall = function ( - code: string, - options: Importer | TransformOptions = {}, - importer: Importer = noopImporter, -): NodePath { - if (typeof options !== 'object') { - importer = options; - options = {}; - } - - return parseDefault( - code, - { - filename: 'file.tsx', - parserOpts: { plugins: ['typescript'] }, - ...options, - }, - importer, - false, - ); -}; - -export const parse = buildTestParser(parseDefault as Parse); -export const parseTypescript = buildTestParser(parseTS as Parse); - -function buildTestParser(parseFunction: Parse): Parse { - parseFunction.statement = function ( - this: Parse, - src: string, - importer: Importer | TransformOptions | number = noopImporter, - options: TransformOptions | number = {}, - index = 0, - ): NodePath { - if (typeof options === 'number') { - index = options; - options = {}; - } - if (typeof importer === 'number') { - index = importer; - importer = noopImporter; - } else if (typeof importer === 'object') { - options = importer; - importer = noopImporter; - } - const root = this(src, options, importer, false); - - if (index < 0) { - index = root.node.body.length + index; - } - - return root.get('body')[index] as unknown as NodePath; - }; - - parseFunction.statementLast = function ( - this: Parse, - src: string, - importer: Importer | TransformOptions = noopImporter, - options: TransformOptions = {}, - ): NodePath { - if (typeof importer === 'object') { - options = importer; - importer = noopImporter; - } - - return this.statement(src, importer, options, -1); - }; - - parseFunction.expression = function ( - this: Parse, - src: string, - importer: Importer | TransformOptions = noopImporter, - options: TransformOptions = {}, - ): NodePath { - if (typeof importer === 'object') { - options = importer; - importer = noopImporter; - } - - return this.statement( - `(${src})`, - importer, - options, - ).get('expression') as unknown as NodePath; - }; - - parseFunction.expressionLast = function ( - this: Parse, - src: string, - importer: Importer | TransformOptions = noopImporter, - options: TransformOptions = {}, - ): NodePath { - if (typeof importer === 'object') { - options = importer; - importer = noopImporter; - } - - return this.statement(src, importer, options, -1).get( - 'expression', - ) as unknown as NodePath; - }; - - return parseFunction; -} - -/** - * Importer that doesn't resolve any values - */ -export const noopImporter: Importer = (): null => { - return null; -}; -/** - * Builds an importer where the keys are import paths and the values are AST nodes - */ -export function makeMockImporter( - mocks: Record< - string, - ( - stmtLast: ( - code: string, - isTs?: boolean, - index?: number, - ) => NodePath, - ) => NodePath - > = {}, -): Importer { - const stmtLast = ( - code: string, - isTs = false, - index = -1, - ): NodePath => { - const parser = isTs ? parseTypescript : parse; - - return parser.statement(code, importer, index); - }; - let cache: Record = Object.create(null); - const importer: Importer = (path: ImportPath): NodePath | null => { - const source = path.node.source?.value; - - if (!source) { - throw new Error(`Cannot find mock source on ImportPath for ${path.type}`); - } - - if (cache[source] === undefined) { - cache[source] = mocks[source]?.(stmtLast); - } - - return cache[source]; - }; - - afterEach(() => { - cache = Object.create(null); - }); - - return importer; -} diff --git a/packages/react-docgen/tsconfig.json b/packages/react-docgen/tsconfig.json deleted file mode 100644 index a7595ddbc6d..00000000000 --- a/packages/react-docgen/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "declaration": true, - "outDir": "./dist" - }, - "exclude": ["**/__tests__/**/*", "**/__mocks__/**/*", "**/__fixtures__/**/*"], - "include": ["src/**/*"] -} diff --git a/packages/react-docgen/vitest.config.ts b/packages/react-docgen/vitest.config.ts deleted file mode 100644 index e58628139e2..00000000000 --- a/packages/react-docgen/vitest.config.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { defineConfig } from 'vitest/config'; - -export default defineConfig({ - test: { - name: 'lib', - setupFiles: ['./tests/setupTestFramework.ts'], - include: ['**/__tests__/**/*-test.ts', '**/tests/integration/**/*-test.ts'], - deps: { - interopDefault: false, - }, - coverage: { - all: true, - include: ['src/**'], - provider: 'v8', - reporter: ['text', 'lcov'], - }, - }, -}); diff --git a/packages/website/.gitignore b/packages/website/.gitignore deleted file mode 100644 index 7da71d862e8..00000000000 --- a/packages/website/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.next -.netlify diff --git a/packages/website/.nvmrc b/packages/website/.nvmrc deleted file mode 100644 index 442c7587a99..00000000000 --- a/packages/website/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -22.20.0 diff --git a/packages/website/README.md b/packages/website/README.md deleted file mode 100644 index 36c569097c1..00000000000 --- a/packages/website/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# react-docgen website - - -## Local Development - -First, run `pnpm install` to install the dependencies. - -Then, run `pnpm dev` to start the development server and visit localhost:3000. - -## License - -This project is licensed under the MIT License. diff --git a/packages/website/eslint.config.mjs b/packages/website/eslint.config.mjs deleted file mode 100644 index b2e945ca838..00000000000 --- a/packages/website/eslint.config.mjs +++ /dev/null @@ -1,28 +0,0 @@ -import path from 'node:path'; -import { globalIgnores } from 'eslint/config'; -import { fileURLToPath } from 'node:url'; -import { FlatCompat } from '@eslint/eslintrc'; -import tseslint from 'typescript-eslint'; -import baseConfig from '../../eslint.config.mjs'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const compat = new FlatCompat({ - baseDirectory: __dirname, -}); - -export default tseslint.config([ - globalIgnores(['**/.next/']), - ...baseConfig, - ...compat.config({ - extends: ['next/core-web-vitals'], - settings: { - next: { - rootDir: __dirname, - }, - }, - rules: { - 'import/no-anonymous-default-export': 'off', - }, - }), -]); diff --git a/packages/website/netlify.toml b/packages/website/netlify.toml deleted file mode 100644 index 9f7473047d2..00000000000 --- a/packages/website/netlify.toml +++ /dev/null @@ -1,4 +0,0 @@ -[build] -command = "pnpm build" -publish = ".next" -ignore = "git diff --quiet $COMMIT_REF $CACHED_COMMIT_REF . ../react-docgen ../../pnpm-lock.yaml" diff --git a/packages/website/next-env.d.ts b/packages/website/next-env.d.ts deleted file mode 100644 index 52e831b4342..00000000000 --- a/packages/website/next-env.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -/// -/// - -// NOTE: This file should not be edited -// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. diff --git a/packages/website/next.config.mjs b/packages/website/next.config.mjs deleted file mode 100644 index 675dd6cf1f5..00000000000 --- a/packages/website/next.config.mjs +++ /dev/null @@ -1,17 +0,0 @@ -import nextra from 'nextra'; - -const withNextra = nextra({ - theme: 'nextra-theme-docs', - themeConfig: './src/theme.config.tsx', -}); - -export default withNextra({ - webpack: (config) => { - if (!config.resolve.fallback) config.resolve.fallback = {}; - - config.resolve.fallback.fs = false; - config.resolve.aliasFields = ['browser']; - - return config; - }, -}); diff --git a/packages/website/package.json b/packages/website/package.json deleted file mode 100644 index 1a72bde77fb..00000000000 --- a/packages/website/package.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "name": "@react-docgen-internal/website", - "private": true, - "version": "0.0.0", - "description": "react-docgen website", - "scripts": { - "dev": "nx exec -- next dev", - "build": "NODE_ENV=production nx exec -- next build", - "start": "nx exec -- next start" - }, - "author": "Daniel Tschinder (http://github.com/danez)", - "license": "MIT", - "dependencies": { - "@codemirror/lang-javascript": "6.2.4", - "@codemirror/lang-json": "6.0.2", - "@codemirror/view": "6.38.3", - "@headlessui/react": "2.2.9", - "@types/react": "19.1.14", - "@types/react-dom": "19.1.9", - "@uiw/react-codemirror": "4.25.2", - "clsx": "2.1.1", - "next": "15.5.4", - "next-themes": "0.4.6", - "nextra": "3.3.1", - "nextra-theme-docs": "3.3.1", - "postcss": "8.5.6", - "postcss-lightningcss": "1.0.2", - "react": "19.1.1", - "react-docgen": "workspace:8.0.1", - "react-dom": "19.1.1", - "tailwindcss": "3.4.17" - }, - "browserslist": [ - "chrome 64", - "edge 79", - "firefox 67", - "opera 51", - "safari 12" - ], - "nx": { - "targets": { - "build": { - "dependsOn": [ - "^build" - ], - "outputs": [ - "{projectRoot}/.next" - ] - }, - "dev": { - "dependsOn": [ - "^build" - ] - }, - "start": { - "dependsOn": [ - "build" - ] - } - } - } -} diff --git a/packages/website/postcss.config.js b/packages/website/postcss.config.js deleted file mode 100644 index 5c6ce1f84af..00000000000 --- a/packages/website/postcss.config.js +++ /dev/null @@ -1,7 +0,0 @@ -/** @type {import('postcss').Postcss} */ -module.exports = { - plugins: { - tailwindcss: {}, - 'postcss-lightningcss': {}, - }, -}; diff --git a/packages/website/public/.keep b/packages/website/public/.keep deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/packages/website/public/_redirects b/packages/website/public/_redirects deleted file mode 100644 index a175d99e7d8..00000000000 --- a/packages/website/public/_redirects +++ /dev/null @@ -1,2 +0,0 @@ -/docs/reference/handlers/proptype-handler /docs/reference/handlers/prop-type-handler -/docs/reference/documentation /docs/reference/documentation/basic diff --git a/packages/website/public/favicon.ico b/packages/website/public/favicon.ico deleted file mode 100644 index 38fd8641cbc..00000000000 Binary files a/packages/website/public/favicon.ico and /dev/null differ diff --git a/packages/website/public/robots.txt b/packages/website/public/robots.txt deleted file mode 100644 index eb0536286f3..00000000000 --- a/packages/website/public/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -User-agent: * -Disallow: diff --git a/packages/website/src/components/ContentMissing.tsx b/packages/website/src/components/ContentMissing.tsx deleted file mode 100644 index cb68f0b9755..00000000000 --- a/packages/website/src/components/ContentMissing.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Callout } from 'nextra/components'; - -export default function ContentMissing() { - return ( - - This content hasn't been created yet. - - ); -} diff --git a/packages/website/src/components/Select.tsx b/packages/website/src/components/Select.tsx deleted file mode 100644 index f0c6ed20782..00000000000 --- a/packages/website/src/components/Select.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { - Listbox, - ListboxButton, - ListboxOption, - ListboxOptions, -} from '@headlessui/react'; -import cn from 'clsx'; -import { CheckIcon } from 'nextra/icons'; -import type { ReactElement } from 'react'; - -interface MenuOption { - key: string; - name: ReactElement | string; -} - -interface MenuProps { - selected: MenuOption; - onChange: (option: MenuOption) => void; - options: MenuOption[]; - title?: string; - className?: string; -} - -export function Select({ - options, - selected, - onChange, - title, - className, -}: MenuProps): ReactElement { - return ( - - - cn( - 'h-7 rounded-md px-2 text-xs font-medium transition-colors', - open - ? 'dark:bg-primary-100/10 bg-gray-200 text-gray-900 dark:text-gray-50' - : hover - ? 'dark:bg-primary-100/5 bg-gray-100 text-gray-900 dark:text-gray-50' - : 'text-gray-600 dark:text-gray-400', - focus && 'nextra-focusable', - className, - ) - } - > - {selected.name} - - - cn( - 'nextra-focus', - open ? 'opacity-100' : 'opacity-0', - 'z-20 max-h-64 min-w-[--button-width] rounded-md border border-black/5 bg-[rgb(var(--nextra-bg),.8)] py-1 text-sm shadow-lg backdrop-blur-lg transition-opacity motion-reduce:transition-none dark:border-white/20', - ) - } - > - {options.map((option) => ( - - cn( - focus - ? 'bg-primary-50 text-primary-600 dark:bg-primary-500/10' - : 'text-gray-800 dark:text-gray-100', - 'cursor-pointer whitespace-nowrap px-3 py-1.5', - 'transition-colors', - option.key === selected.key && - 'flex items-center justify-between gap-3', - ) - } - > - {option.name} - {option.key === selected.key && } - - ))} - - - ); -} diff --git a/packages/website/src/components/playground/OptionPanel.tsx b/packages/website/src/components/playground/OptionPanel.tsx deleted file mode 100644 index 810f941aed0..00000000000 --- a/packages/website/src/components/playground/OptionPanel.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import React from 'react'; -import { Select } from '../Select'; - -interface OptionPanelProps { - language: Language; - onLanguageChange: (language: Language) => void; -} - -export enum Language { - FLOW = 'flow', - JAVASCRIPT = 'js', - TYPESCRIPT = 'ts', -} - -const options = [ - { key: Language.TYPESCRIPT, name: 'TypeScript' }, - { key: Language.JAVASCRIPT, name: 'JavaScript' }, - { key: Language.FLOW, name: 'Flow' }, -]; - -export default function OptionPanel({ - language, - onLanguageChange, -}: OptionPanelProps) { - const selectedOption = options.find((option) => option.key === language); - - if (!selectedOption) { - throw new Error(`Could not find language '${language}'`); - } - - return ( - <> -