├── .nvmrc
├── packages
├── recon-config
│ ├── src
│ │ ├── __tests__
│ │ │ ├── __fixtures__
│ │ │ │ ├── empty
│ │ │ │ │ └── .gitignore
│ │ │ │ └── all
│ │ │ │ │ └── .reconrc
│ │ │ ├── index.test.js
│ │ │ ├── configFromWebpack.test.js
│ │ │ ├── getConfig.test.js
│ │ │ └── createConfig.test.js
│ │ ├── shared.js
│ │ ├── index.js
│ │ ├── createConfig.js
│ │ ├── getConfig.js
│ │ └── configFromWebpack.js
│ ├── package.json
│ └── README.md
├── recon-engine
│ ├── src
│ │ ├── engine
│ │ │ ├── __tests__
│ │ │ │ ├── __fixtures__
│ │ │ │ │ └── basic-app
│ │ │ │ │ │ ├── query.graphql
│ │ │ │ │ │ └── src
│ │ │ │ │ │ ├── avatar.js
│ │ │ │ │ │ ├── button.js
│ │ │ │ │ │ ├── list.js
│ │ │ │ │ │ ├── user-list.js
│ │ │ │ │ │ ├── app.js
│ │ │ │ │ │ └── notes.js
│ │ │ │ ├── __snapshots__
│ │ │ │ │ └── createEngine.test.js.snap
│ │ │ │ └── createEngine.test.js
│ │ │ └── createEngine.js
│ │ ├── index.js
│ │ ├── parse
│ │ │ ├── __tests__
│ │ │ │ ├── __fixtures__
│ │ │ │ │ ├── empty
│ │ │ │ │ │ └── src.js
│ │ │ │ │ ├── re-exports
│ │ │ │ │ │ └── src.js
│ │ │ │ │ ├── no-components
│ │ │ │ │ │ └── src.js
│ │ │ │ │ ├── dynamic-components
│ │ │ │ │ │ └── src.js
│ │ │ │ │ ├── basic-components
│ │ │ │ │ │ └── src.js
│ │ │ │ │ ├── enhanced-components
│ │ │ │ │ │ └── src.js
│ │ │ │ │ └── real-world-lystable
│ │ │ │ │ │ └── src.js
│ │ │ │ └── parseModule.test.js
│ │ │ └── parseModule.js
│ │ ├── __tests__
│ │ │ └── index.test.js
│ │ ├── utils
│ │ │ ├── isReactComponent.js
│ │ │ └── __tests__
│ │ │ │ └── isReactComponent.test.js
│ │ └── query
│ │ │ └── createSchema.js
│ ├── README.md
│ ├── package.json
│ └── docs
│ │ └── dev-guide.md
├── recon-stats
│ ├── src
│ │ ├── index.js
│ │ ├── __tests__
│ │ │ ├── index.test.js
│ │ │ ├── makeStats.test.js
│ │ │ └── pullStats.test.js
│ │ ├── pullStats.js
│ │ ├── query.graphql
│ │ └── makeStats.js
│ ├── README.md
│ └── package.json
├── recon-server
│ ├── src
│ │ ├── index.js
│ │ ├── __tests__
│ │ │ └── index.test.js
│ │ └── createServer.js
│ ├── README.md
│ └── package.json
└── recon-cli
│ ├── README.md
│ ├── package.json
│ └── src
│ └── index.js
├── .travis.yml
├── .eslintignore
├── .gitignore
├── lerna.json
├── .flowconfig
├── .eslintrc
├── wallaby.js
├── LICENSE.md
├── docs
└── dev-guide.md
├── CONTRIBUTING.md
├── package.json
├── flow
├── lodash.js.flow
└── babel.js.flow
└── README.md
/.nvmrc:
--------------------------------------------------------------------------------
1 | v7.7.3
2 |
--------------------------------------------------------------------------------
/packages/recon-config/src/__tests__/__fixtures__/empty/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/engine/__tests__/__fixtures__/basic-app/query.graphql:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/index.js:
--------------------------------------------------------------------------------
1 | exports.createEngine = require('./engine/createEngine');
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "7"
4 | before_script:
5 | - npm run bootstrap
6 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/parse/__tests__/__fixtures__/empty/src.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 |
3 | // EMPTY
4 |
--------------------------------------------------------------------------------
/packages/recon-config/src/__tests__/__fixtures__/all/.reconrc:
--------------------------------------------------------------------------------
1 | {
2 | "files": "**/*.js",
3 | "resolve": {}
4 | }
5 |
--------------------------------------------------------------------------------
/packages/recon-stats/src/index.js:
--------------------------------------------------------------------------------
1 | const pullStats = require('./pullStats');
2 |
3 | exports.pullStats = pullStats;
4 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | **/node_modules/**/*.js
2 | **/__fixtures__/**/*.js
3 | **/dist/**/*.js
4 | **/lib/**/*.js
5 | **/*.js.flow
6 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/parse/__tests__/__fixtures__/re-exports/src.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | export {a as b} from 'src';
3 |
--------------------------------------------------------------------------------
/packages/recon-server/src/index.js:
--------------------------------------------------------------------------------
1 | const createServer = require('./createServer');
2 |
3 | exports.createServer = createServer;
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | lib/
2 | node_modules/
3 | dist/
4 | .idea/
5 | npm-debug.log
6 | lerna-debug.log
7 | __local__/
8 | *.__local__.*
9 | .tmp/
10 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "lerna": "2.0.0-beta.38",
3 | "version": "0.0.7",
4 | "hoist": true,
5 | "packages": [
6 | "packages/*"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/packages/recon-config/src/shared.js:
--------------------------------------------------------------------------------
1 | /** File name to look for configuration */
2 | const CONFIG_FILE_NAME = '.reconrc';
3 |
4 | exports.CONFIG_FILE_NAME = CONFIG_FILE_NAME;
5 |
--------------------------------------------------------------------------------
/packages/recon-stats/README.md:
--------------------------------------------------------------------------------
1 | recon-stats
2 | ===========
3 |
4 | Generate stats for your application
5 |
6 | *Part of [Recon: Code Intelligence for React](https://github.com/lystable/recon)*
7 |
--------------------------------------------------------------------------------
/.flowconfig:
--------------------------------------------------------------------------------
1 | [ignore]
2 | .*/node_modules/react\(-dom\)?/.*
3 | .*/.*\.config\.js
4 | .*/Gulpfile\.js
5 | .*/json5/test/.*
6 |
7 | [include]
8 |
9 | [libs]
10 | flow/
11 |
12 | [options]
13 |
--------------------------------------------------------------------------------
/packages/recon-engine/README.md:
--------------------------------------------------------------------------------
1 | recon-engine
2 | ============
3 |
4 | Engine runtime for Recon intelligence.
5 |
6 | *Part of [Recon: Code Intelligence for React](https://github.com/lystable/recon)*
7 |
--------------------------------------------------------------------------------
/packages/recon-server/README.md:
--------------------------------------------------------------------------------
1 | recon-server
2 | ============
3 |
4 | GraphQL server in front of a Recon Engine.
5 |
6 | *Part of [Recon: Code Intelligence for React](https://github.com/lystable/recon)*
7 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/engine/__tests__/__fixtures__/basic-app/src/avatar.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 |
4 | export default function Avatar({src}) {
5 | return ;
6 | }
7 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/__tests__/index.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-env jest */
2 | const api = require('../index');
3 |
4 | it('should provide expected api', () => {
5 | expect(api.createEngine).toBeInstanceOf(Function);
6 | });
7 |
--------------------------------------------------------------------------------
/packages/recon-server/src/__tests__/index.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-env jest */
2 | const api = require('../index');
3 |
4 | it('should provide expected api', () => {
5 | expect(api.createServer).toBeInstanceOf(Function);
6 | });
7 |
--------------------------------------------------------------------------------
/packages/recon-stats/src/__tests__/index.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-env jest */
2 | const api = require('../index');
3 |
4 | it('should provide expected api', () => {
5 | expect(api.pullStats).toBeInstanceOf(Function);
6 | });
7 |
--------------------------------------------------------------------------------
/packages/recon-stats/src/__tests__/makeStats.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-env jest */
2 |
3 | // const makeStats = require('../makeStats');
4 | it('should generate stats from data', () => {
5 | expect({}).toMatchObject({});
6 | });
7 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/parse/__tests__/__fixtures__/no-components/src.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import imported from './imported';
3 |
4 | export class MyClass {}
5 |
6 | const myValue = 5;
7 |
8 | export default myValue;
9 |
--------------------------------------------------------------------------------
/packages/recon-stats/src/__tests__/pullStats.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-env jest */
2 | // const pullStats = require('../pullStats');
3 |
4 | it('should generate stats given an engine to query', () => {
5 | expect({}).toMatchObject({});
6 | });
7 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/engine/__tests__/__fixtures__/basic-app/src/button.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 |
4 | export default function Button({theme, children}) {
5 | return {children} ;
6 | }
7 |
--------------------------------------------------------------------------------
/packages/recon-config/src/__tests__/index.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-env jest */
2 | const api = require('../index');
3 |
4 | it('should provide expected api', () => {
5 | expect(api.getConfig).toBeInstanceOf(Function);
6 | expect(api.createConfig).toBeInstanceOf(Function);
7 | });
8 |
--------------------------------------------------------------------------------
/packages/recon-cli/README.md:
--------------------------------------------------------------------------------
1 | recon-cli
2 | =========
3 |
4 | Command line interface for wielding the power of Recon.
5 |
6 | *Part of [Recon: Code Intelligence for React](https://github.com/lystable/recon)*
7 |
8 | Once you've run `recon` the world of power should just be a `help` command away!
9 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/parse/__tests__/__fixtures__/dynamic-components/src.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 |
4 | function makeComponent(staticProps) {
5 | return props =>
;
6 | }
7 |
8 | export const Flex = makeComponent({style: {display: 'flex'}});
9 |
--------------------------------------------------------------------------------
/packages/recon-config/src/index.js:
--------------------------------------------------------------------------------
1 | const getConfig = require('./getConfig');
2 | const createConfig = require('./createConfig');
3 | const configFromWebpack = require('./configFromWebpack');
4 |
5 | exports.getConfig = getConfig;
6 | exports.createConfig = createConfig;
7 | exports.configFromWebpack = configFromWebpack;
8 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/engine/__tests__/__snapshots__/createEngine.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`should respond to query as expected: basic-app 1`] = `
4 | Object {
5 | "errors": Array [
6 | [GraphQLError: Syntax Error GraphQL request (1:2) Expected Name, found }
7 |
8 | 1: {}
9 | ^
10 | 2:
11 | ],
12 | ],
13 | }
14 | `;
15 |
--------------------------------------------------------------------------------
/packages/recon-stats/src/pullStats.js:
--------------------------------------------------------------------------------
1 | const Jetpack = require('fs-jetpack');
2 | const makeStats = require('./makeStats');
3 |
4 | /** Given a recon-engine instance pull stats */
5 | function pullStats(engine) {
6 | const query = Jetpack.cwd(__dirname).read('query.graphql', 'utf8');
7 | return engine.runQuery(query).then(makeStats);
8 | }
9 |
10 | module.exports = pullStats;
11 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/engine/__tests__/__fixtures__/basic-app/src/list.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 |
4 | export function ListItem({type, children}) {
5 | return (
6 |
7 | {children}
8 |
9 | );
10 | }
11 |
12 | export default function List({children, type}) {
13 | return (
14 |
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "flowtype"
4 | ],
5 | "extends": [
6 | "lystable",
7 | "prettier",
8 | "plugin:flowtype/recommended",
9 | "prettier",
10 | "prettier/flowtype"
11 | ],
12 | "env": {
13 | "node": true
14 | },
15 | "rules": {
16 | "max-len": [2, 140],
17 | "spaced-comment": 0,
18 | "arrow-body-style": 0,
19 | "no-confusing-arrow": 0
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/parse/__tests__/__fixtures__/basic-components/src.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 |
4 | export function FunctionalComponent() {
5 | return Hello world!
;
6 | }
7 |
8 | export const ArrowFunctionalComponent = () =>
;
9 |
10 | export default class ClassComponent {
11 | render() {
12 | return ;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/wallaby.js:
--------------------------------------------------------------------------------
1 | module.exports = function() {
2 | return {
3 | testFramework: 'jest',
4 | files: ['packages/**/*', {pattern: '**/*.test.js', ignore: true}],
5 | tests: [
6 | 'packages/**/src/**/__tests__/**/*.test.js',
7 | {pattern: 'packages/**/node_modules/**/__tests__/**', ignore: true},
8 | ],
9 | env: {
10 | type: 'node',
11 | runner: 'node',
12 | },
13 | workers: {
14 | recycle: true,
15 | },
16 | filesWithNoCoverageCalculated: ['**/node_modules/**'],
17 | debug: true,
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright 2016 Lystable Industries
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | http://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | See the License for the specific language governing permissions and
13 | limitations under the License.
14 |
--------------------------------------------------------------------------------
/packages/recon-config/src/__tests__/configFromWebpack.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-env jest */
2 | const configFromWebpack = require('../configFromWebpack');
3 |
4 | it('should return expected configuration', () => {
5 | const cwd = '/root/test';
6 | const webpackConfig = {
7 | context: '/root/test/src',
8 | resolve: {
9 | roots: ['/root/test/src/core'],
10 | extensions: ['.test', ''],
11 | },
12 | };
13 | const reconConfig = {
14 | context: 'src',
15 | resolve: {
16 | roots: ['core'],
17 | extensions: ['.test'],
18 | },
19 | };
20 |
21 | expect(configFromWebpack(webpackConfig, {cwd})).toMatchObject(reconConfig);
22 | });
23 |
--------------------------------------------------------------------------------
/packages/recon-server/src/createServer.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const graphqlHTTP = require('express-graphql');
3 | const http = require('http');
4 |
5 | /** Given a recon engine create a http-server for querying */
6 | function createServer(engine, {port = 4000} = {}) {
7 | const app = express();
8 |
9 | app.use(
10 | '/graphql',
11 | graphqlHTTP({
12 | schema: engine.schema,
13 | graphiql: true,
14 | })
15 | );
16 |
17 | const server = http.createServer(app);
18 |
19 | return new Promise(accept => {
20 | server.listen(port, () => {
21 | accept(server);
22 | });
23 | });
24 | }
25 |
26 | module.exports = createServer;
27 |
--------------------------------------------------------------------------------
/packages/recon-config/src/createConfig.js:
--------------------------------------------------------------------------------
1 | const Jetpack = require('fs-jetpack');
2 | const Path = require('path');
3 | const {CONFIG_FILE_NAME} = require('./shared');
4 |
5 | /**
6 | * Create a new config file with user defined configuration
7 | */
8 | function createConfig(userConfig, {cwd = process.cwd()} = {}) {
9 | // TODO: Search for definition within package.json
10 | const rc = Jetpack.cwd(cwd).exists(CONFIG_FILE_NAME);
11 | if (rc) {
12 | throw new Error('Oops! Looks like you already have a .reconrc file!');
13 | }
14 | Jetpack.cwd(cwd).write(CONFIG_FILE_NAME, userConfig);
15 | return Path.resolve(cwd, CONFIG_FILE_NAME);
16 | }
17 |
18 | module.exports = createConfig;
19 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/engine/__tests__/__fixtures__/basic-app/src/user-list.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 | import Button from './button';
4 | import List, {ListItem} from './list';
5 |
6 | function UserItem({user}) {
7 | return (
8 |
9 |
10 | {user.name}
11 | Remove User
12 |
13 | );
14 | }
15 |
16 | export default function UserList({users}) {
17 | return (
18 |
19 | {users.map(user => {
20 | return ;
21 | })}
22 |
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/engine/__tests__/__fixtures__/basic-app/src/app.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 | import ReactDOM from 'react-dom';
4 |
5 | import Button from './button';
6 | import Notes from './notes';
7 | import UserList from './user-list';
8 |
9 | const users = [];
10 |
11 | const App = ({users}) => (
12 |
13 |
My Application
14 |
15 | Users
16 | Add User
17 |
18 |
19 |
20 |
21 | );
22 |
23 | function renderApp() {
24 | ReactDOM.render( , document.getElementById('app'));
25 | }
26 |
27 | renderApp();
28 |
--------------------------------------------------------------------------------
/packages/recon-config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "recon-config",
3 | "version": "0.0.7",
4 | "description": "An api for discovering and reading config for recon.",
5 | "main": "src/index.js",
6 | "keywords": [
7 | "intellisense",
8 | "components",
9 | "react"
10 | ],
11 | "author": "Lystable Industries ",
12 | "license": "Apache-2.0",
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/lystable/recon.git"
16 | },
17 | "bugs": {
18 | "url": "https://github.com/lystable/recon/issues"
19 | },
20 | "homepage": "https://github.com/lystable/recon",
21 | "dependencies": {
22 | "fs-jetpack": "^0.13.1"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/packages/recon-config/src/__tests__/getConfig.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-env jest */
2 | const Path = require('path');
3 |
4 | const getConfig = require('../getConfig');
5 |
6 | it('should read a config file with no user config', () => {
7 | const cwd = Path.resolve(__dirname, '__fixtures__/all');
8 | const uc = undefined;
9 | expect(getConfig(uc, {cwd})).toMatchObject({
10 | files: '**/*.js',
11 | resolve: {},
12 | });
13 | });
14 |
15 | it('should read a config file with user config', () => {
16 | const cwd = Path.resolve(__dirname, '__fixtures__/all');
17 | const uc = {files: 'test.js'};
18 | expect(getConfig(uc, {cwd})).toMatchObject({
19 | files: 'test.js',
20 | resolve: {},
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/packages/recon-stats/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "recon-stats",
3 | "version": "0.0.7",
4 | "description": "Generate stats from recon intelligence",
5 | "main": "src/index.js",
6 | "keywords": [
7 | "intellisense",
8 | "components",
9 | "react"
10 | ],
11 | "author": "Lystable Industries ",
12 | "license": "Apache-2.0",
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/lystable/recon.git"
16 | },
17 | "bugs": {
18 | "url": "https://github.com/lystable/recon/issues"
19 | },
20 | "homepage": "https://github.com/lystable/recon",
21 | "dependencies": {
22 | "fs-jetpack": "^0.13.1",
23 | "lodash": "^4.15.0"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/packages/recon-server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "recon-server",
3 | "version": "0.0.7",
4 | "description": "A GraphQL server for querying the Recon Engine.",
5 | "main": "src/index.js",
6 | "keywords": [
7 | "intellisense",
8 | "components",
9 | "react"
10 | ],
11 | "author": "Lystable Industries ",
12 | "license": "Apache-2.0",
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/lystable/recon.git"
16 | },
17 | "bugs": {
18 | "url": "https://github.com/lystable/recon/issues"
19 | },
20 | "homepage": "https://github.com/lystable/recon",
21 | "dependencies": {
22 | "express": "^4.14.0",
23 | "express-graphql": "^0.6.3",
24 | "graphql": "^0.9.1"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/packages/recon-stats/src/query.graphql:
--------------------------------------------------------------------------------
1 | {
2 | modules {
3 | path
4 | }
5 |
6 | components {
7 | id,
8 | name,
9 | module {
10 | path
11 | },
12 | dependencies {
13 | name,
14 | component {
15 | id,
16 | pathEnhancements {
17 | type
18 | }
19 | module {
20 | path
21 | }
22 | },
23 | usages {
24 | props {
25 | name,
26 | valueType
27 | }
28 | }
29 | },
30 | dependants {
31 | name,
32 | component {
33 | id,
34 | name,
35 | module {
36 | path
37 | }
38 | }
39 | usages {
40 | props {
41 | name,
42 | valueType
43 | }
44 | }
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/packages/recon-config/src/getConfig.js:
--------------------------------------------------------------------------------
1 | const Jetpack = require('fs-jetpack');
2 | const {CONFIG_FILE_NAME} = require('./shared');
3 |
4 | /**
5 | * Generate a full config for a working directory and any user config
6 | * - Will manage any sensible merging of configs as complexity grows
7 | */
8 | function getConfig(uc, {cwd = process.cwd()} = {}) {
9 | // TODO: Search for definition within package.json
10 | const rc = Jetpack.cwd(cwd).read(CONFIG_FILE_NAME, 'json');
11 | if (!rc) {
12 | throw new Error(
13 | "Oops! Doesn't look like there is a valid .reconrc file" +
14 | 'defined in your project root. See: https://github' +
15 | '.com/lystable/recon/tree/master/packages/recon-config for info.'
16 | ); // eslint-disable-line max-len
17 | }
18 | return Object.assign({}, rc, uc);
19 | }
20 |
21 | module.exports = getConfig;
22 |
--------------------------------------------------------------------------------
/packages/recon-config/src/configFromWebpack.js:
--------------------------------------------------------------------------------
1 | const Path = require('path');
2 |
3 | /** Given webpack configuration object return recon config */
4 | function configFromWebpack(webpackConfig, {cwd = process.cwd()} = {}) {
5 | const config = {};
6 |
7 | if (webpackConfig.context) {
8 | config.context = Path.relative(cwd, webpackConfig.context);
9 | }
10 |
11 | if (webpackConfig.resolve) {
12 | const resolve = {};
13 |
14 | if (webpackConfig.resolve.extensions) {
15 | resolve.extensions = webpackConfig.resolve.extensions.filter(x => !!x);
16 | }
17 |
18 | const roots = webpackConfig.resolve.root || webpackConfig.resolve.roots; // support v1 & v2
19 | if (roots) {
20 | resolve.roots = roots.map(p =>
21 | Path.relative(webpackConfig.context || cwd, p));
22 | }
23 |
24 | config.resolve = resolve;
25 | }
26 |
27 | return config;
28 | }
29 |
30 | module.exports = configFromWebpack;
31 |
--------------------------------------------------------------------------------
/packages/recon-config/src/__tests__/createConfig.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-env jest */
2 | const Path = require('path');
3 | const Jetpack = require('fs-jetpack');
4 |
5 | const createConfig = require('../createConfig');
6 |
7 | it('should throw if a config already exists', () => {
8 | const cwd = Path.resolve(__dirname, '__fixtures__/all');
9 | expect(() => createConfig({}, {cwd})).toThrow();
10 | });
11 |
12 | it('should create a new configuration file', () => {
13 | const uc = {
14 | resolve: {
15 | extensions: ['.jsx', '.js'],
16 | },
17 | };
18 | const cwd = Path.resolve(__dirname, '__fixtures__/empty');
19 | const file = createConfig(uc, {cwd});
20 | expect(Jetpack.cwd(cwd).exists('.reconrc')).toBe('file');
21 | expect(Jetpack.cwd(cwd).read('.reconrc', 'json')).toMatchObject(uc);
22 | expect(file).toMatch(Path.resolve(cwd, '.reconrc'));
23 | // finally, clean up test
24 | Jetpack.cwd(cwd).remove('.reconrc');
25 | });
26 |
--------------------------------------------------------------------------------
/packages/recon-engine/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "recon-engine",
3 | "version": "0.0.7",
4 | "description": "The engine runtime for Recon.",
5 | "main": "src/index.js",
6 | "keywords": [
7 | "intellisense",
8 | "components",
9 | "react"
10 | ],
11 | "author": "Lystable Industries ",
12 | "license": "Apache-2.0",
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/lystable/recon.git"
16 | },
17 | "bugs": {
18 | "url": "https://github.com/lystable/recon/issues"
19 | },
20 | "homepage": "https://github.com/lystable/recon",
21 | "dependencies": {
22 | "babel-traverse": "^6.23.1",
23 | "babel-types": "^6.23.0",
24 | "babylon": "^6.16.1",
25 | "fs-jetpack": "^0.13.1",
26 | "glob": "^7.0.5",
27 | "lodash": "^4.15.0"
28 | },
29 | "devDependencies": {
30 | "graphql": "^0.11.7"
31 | },
32 | "peerDependencies": {
33 | "graphql": ">=0.11.0"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/packages/recon-cli/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "recon-cli",
3 | "version": "0.0.7",
4 | "description": "A commandline interface for wielding the power of Recon.",
5 | "main": "src/index.js",
6 | "keywords": [
7 | "intellisense",
8 | "components",
9 | "react"
10 | ],
11 | "author": "Lystable Industries ",
12 | "license": "Apache-2.0",
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/lystable/recon.git"
16 | },
17 | "bugs": {
18 | "url": "https://github.com/lystable/recon/issues"
19 | },
20 | "homepage": "https://github.com/lystable/recon",
21 | "dependencies": {
22 | "dedent": "^0.7.0",
23 | "fs-jetpack": "^0.13.1",
24 | "lodash": "^4.15.0",
25 | "progress": "^1.1.8",
26 | "recon-config": "^0.0.7",
27 | "recon-engine": "^0.0.7",
28 | "recon-server": "^0.0.7",
29 | "recon-stats": "^0.0.7",
30 | "vorpal": "^1.11.4"
31 | },
32 | "bin": {
33 | "recon": "./src/index.js"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/engine/__tests__/createEngine.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-env jest */
2 | const Path = require('path');
3 | const FS = require('fs');
4 |
5 | const createEngine = require('../createEngine');
6 |
7 | function run(path) {
8 | const absPath = Path.resolve(__dirname, '__fixtures__', path);
9 | const query = FS.readFileSync(Path.resolve(absPath, 'query.graphql'), {
10 | encoding: 'utf8',
11 | });
12 |
13 | const engine = createEngine({
14 | files: '**/*.js',
15 | context: Path.resolve(absPath, 'src'),
16 | });
17 |
18 | return new Promise((accept, reject) => {
19 | engine.subscribe(stats => {
20 | if (stats.numModules && stats.canQuery) {
21 | engine.runQuery(query).then(
22 | result => {
23 | // TODO: snapshot tests
24 | expect(result).toMatchSnapshot();
25 | accept();
26 | },
27 | err => reject(err)
28 | );
29 | }
30 | });
31 | });
32 | }
33 |
34 | it('should respond to query as expected: basic-app', () => run('basic-app'));
35 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/engine/__tests__/__fixtures__/basic-app/src/notes.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 | import List, {ListItem} from './list';
4 | import {createContainer, query as q} from 'api/recall';
5 | import {Note} from 'api/resources';
6 |
7 | function NoteItem({note}) {
8 | return (
9 |
10 |
11 | {note.content}
12 |
13 | );
14 | }
15 |
16 | export function Notes({notes}) {
17 | return (
18 |
19 |
Notes
20 |
21 | {notes.map(user => {
22 | return ;
23 | })}
24 |
25 |
26 | );
27 | }
28 |
29 | const contain = createContainer({
30 | queries: {
31 | invoices: q.many(Note, {
32 | params: vars => ({
33 | filter: {
34 | parent: vars.parent,
35 | },
36 | }),
37 | fields: {
38 | content: true,
39 | created_by: {
40 | img: true,
41 | },
42 | },
43 | }),
44 | },
45 | });
46 |
47 | export default contain(Notes);
48 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/parse/__tests__/__fixtures__/enhanced-components/src.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 | import {withState, compose} from 'recompose';
4 | import {createContainer} from 'recall';
5 |
6 | export function FunctionalComponent() {
7 | return Hello world!
;
8 | }
9 |
10 | // Note we currently do not detect this as a "directly enhanced" component
11 | // but rather it can be seen as an "enhancement path" for the
12 | // referenced `FunctionalComponent`. Ie. if `EnhancedFunctionalComponent`
13 | // was referenced as a dep from another component we could trace it back
14 | // to `FunctionalComponent` but mark this as a "enhancement path".
15 | // In the future we may want to discover all these within a module at parse time.
16 | export const EnhancedFunctionalComponent = withState()(FunctionalComponent);
17 |
18 | export const ArrowFunctionalComponent = () =>
;
19 |
20 | const enhance = compose(createContainer(), withState());
21 |
22 | export const EnhancedArrowFunctionalComponent = enhance(() =>
);
23 |
24 | export default class ClassComponent {
25 | render() {
26 | return ;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/docs/dev-guide.md:
--------------------------------------------------------------------------------
1 | Recon Developer Guide
2 | =====================
3 |
4 | The first thing to get to grips with is that Recon is structured as a monorepo
5 | and contains several packages. These are:
6 |
7 | - [recon-engine](../packages/recon-engine) - The powerhouse behind Recon. Parses, structures and provides a query interface.
8 | - [recon-server](../packages/recon-server) - A simple http server which spawns the engine and provides a http graphql interface.
9 | - [recon-cli](../packages/recon-cli) - Command line interface for quickly working with Recon as opposed to using the programmatic api's.
10 | - [recon-config](../packages/recon-config) - Recon configuration management (reads .rc file etc.)
11 | - [recon-stats](../packages/recon-stats) - Generate useful and interesting stats about an application
12 |
13 | ## The code
14 |
15 | - `npm test` will tell you what's up (type checking, linter ([eslint-config-lystable](https://github.com/lystable/guidelines/tree/master/styleguides/eslint-config-lystable)) and unit tests)
16 |
17 | ## Let's get going!
18 |
19 | Depending on where you're wanting to start you may be interested in the more targeted
20 | developer guides:
21 |
22 | - [recon-engine Developer Guide](../packages/recon-engine/docs/dev-guide.md)
23 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Contributing Guidelines
2 | =======================
3 |
4 | ## Got a bug when using Recon against your application source code?
5 |
6 | The nature of Recon and flexibility of Javascript means it is very hard to gather
7 | all the edge cases for usage of React. Therefore the best way for us to debug
8 | and resolve issues is to have a reproducible breaking test case which demonstrates
9 | your usage.
10 |
11 | We therefore ask if you have an issue with the parsing or output of Recon to please
12 | submit a pull request with the following:
13 |
14 | - A test case which demonstrates the code which breaks/doesn't do what you expect.
15 | - In most cases this will be as simple as copying out a fixture and hooking up a new test
16 | which will most likely live either [here](../packages/recon-engine/src/engine/__tests__) or [here](../packages/recon-engine/src/parse/__tests__)
17 | - Title prefixed with `[BUG]`
18 |
19 | ## Got a feature idea?
20 |
21 | We'd love to discuss it! Feel free to submit an issue. Just try to be as descriptive as you can
22 | and preferably include code/output examples since that can really help.
23 |
24 | ## Developing Recon
25 |
26 | Read more about contributing to the codebase in our [Developer Guide](./docs/dev-guide.md)
27 |
28 | At an absolute minimum make sure `npm test` runs! :)
29 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/parse/__tests__/parseModule.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-env jest */
2 | const parseModule = require('../parseModule');
3 | const FS = require('fs');
4 | const Path = require('path');
5 |
6 | describe('react-engine::parse/parseModule', () => {
7 | describe('::parseModule (default)', () => {
8 | function run(path) {
9 | const absPath = Path.resolve(__dirname, '__fixtures__', path);
10 | const src = FS.readFileSync(`${absPath}/src.js`, {encoding: 'utf8'});
11 | const module = {src, path, id: path};
12 | const parsed = parseModule(module);
13 | expect(parsed).toMatchSnapshot();
14 | }
15 |
16 | it('should parse module information as expected: empty', () =>
17 | run('empty'));
18 | it('should parse module information as expected: no-components', () =>
19 | run('no-components'));
20 | it('should parse module information as expected: basic-components', () =>
21 | run('basic-components'));
22 | it('should parse module information as expected: enhanced-components', () =>
23 | run('enhanced-components'));
24 | it('should parse module information as expected: real-world-lystable', () =>
25 | run('real-world-lystable'));
26 | it('should parse module information as expected: re-exports', () =>
27 | run('re-exports'));
28 | it('should parse module information as expected: dynamic-components', () =>
29 | run('dynamic-components'));
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/utils/isReactComponent.js:
--------------------------------------------------------------------------------
1 | const T = require('babel-types');
2 | const {find} = require('lodash');
3 | const traverse = require('babel-traverse').default;
4 |
5 | /** Does a given function path contain JSX? */
6 | function containsJSX(node) {
7 | if (T.isJSXElement(node)) {
8 | return true;
9 | }
10 |
11 | let doesContainJSX = false;
12 | const visitor = {
13 | ReturnStatement(jsxPath) {
14 | if (T.isJSXElement(jsxPath.node.argument)) {
15 | doesContainJSX = true;
16 | jsxPath.stop();
17 | }
18 | },
19 |
20 | noScope: true,
21 | };
22 |
23 | traverse(node, visitor);
24 | return doesContainJSX;
25 | }
26 |
27 | /** Is given path a react component declaration? */
28 | function isReactComponent(node) {
29 | // TODO: Is there a stronger way of determining a "react component"?
30 | // TODO: Accept React.createClass() (unless there is plans to deprecate in *near* future?)
31 |
32 | if (T.isClassDeclaration(node)) {
33 | return !!find(
34 | node.body.body,
35 | bNode => T.isClassMethod(bNode) && bNode.key.name === 'render'
36 | );
37 | }
38 |
39 | if (T.isFunctionDeclaration(node)) {
40 | return containsJSX(node.body);
41 | }
42 |
43 | if (T.isFunctionExpression(node)) {
44 | return containsJSX(node.body);
45 | }
46 |
47 | if (T.isArrowFunctionExpression(node)) {
48 | return containsJSX(node.body);
49 | }
50 |
51 | return false;
52 | }
53 |
54 | module.exports = isReactComponent;
55 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "recon",
4 | "scripts": {
5 | "test:lint": "eslint **/*.js --cache --cache-location .tmp/eslint/",
6 | "test:type": "flow",
7 | "test:unit": "jest --forceExit",
8 | "test": "npm run test:lint && npm run test:type && npm run test:unit",
9 | "pub": "npm run test && lerna publish",
10 | "bootstrap": "lerna bootstrap",
11 | "precommit": "lint-staged",
12 | "postinstall": "npm run bootstrap",
13 | "format": "prettier --single-quote --trailing-comma es5 --no-bracket-spacing --write"
14 | },
15 | "author": "Lystable Industries ",
16 | "license": "Apache-2.0",
17 | "devDependencies": {
18 | "babel-eslint": "7.1.1",
19 | "eslint": "3.18.0",
20 | "eslint-config-airbnb": "14.1.0",
21 | "eslint-config-lystable": "6.0.0",
22 | "eslint-config-prettier": "1.5.0",
23 | "eslint-plugin-flowtype": "2.30.3",
24 | "eslint-plugin-import": "2.2.0",
25 | "eslint-plugin-jsx-a11y": "4.0.0",
26 | "eslint-plugin-react": "6.10.0",
27 | "flow-bin": "0.42.0",
28 | "husky": "^0.13.2",
29 | "jest": "^19.0.2",
30 | "lerna": "2.0.0-beta.38",
31 | "lint-staged": "^3.4.0",
32 | "prettier": "^0.22.0"
33 | },
34 | "jest": {
35 | "coverageDirectory": ".tmp/coverage/",
36 | "collectCoverage": true,
37 | "testEnvironment": "node",
38 | "testMatch": [
39 | "**/__tests__/**/(*.)(test).js?(x)"
40 | ]
41 | },
42 | "lint-staged": {
43 | "*.js": [
44 | "npm run format",
45 | "git add",
46 | "npm run test:lint"
47 | ]
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/packages/recon-config/README.md:
--------------------------------------------------------------------------------
1 | recon-config
2 | ============
3 |
4 | Recon configuration management.
5 |
6 | *Part of [Recon: Code Intelligence for React](https://github.com/lystable/recon)*
7 |
8 | ### Configuration
9 |
10 | All projects hoping to use Recon should have a `.reconrc` file at their root.
11 |
12 | - `context` - Where should we search for files (default `process.cwd()`)
13 | - `files` *(required)* - [Glob](https://en.wikipedia.org/wiki/Glob_(programming)) pattern telling which files
14 | recon should parse. This should be pretty much all js files in your application which are likely to
15 | be used by or use a component. It is recommended to exclude any meta files such as tests.
16 | - `resolve` - Namespace to help recon resolve require/import paths correctly
17 | - `roots` - An array of paths (relative to working directory) from which to resolve paths.
18 | Eg. `require('components/button')` and `roots: [core]` would look in `core/components/button`
19 | - `extensions` - An array of extensions to include when resolving paths without an explicit extension.
20 | Default: `['.js', '.jsx']`
21 | - `ignore` - Regex to exclude paths from being parsed (default `/node_modules/`)
22 | - Note: atm we don't support flags, pr's welcome!
23 |
24 | ##### Example configuration
25 |
26 | ```json
27 | {
28 | "context": "src",
29 | "files": "**/!(*-test|*-tests|*.manifest).js*",
30 | "resolve": {
31 | "roots": [
32 | "core",
33 | ""
34 | ]
35 | },
36 | "ignore": "/node_modules/"
37 | }
38 | ```
39 |
40 | > Note: If you make changes to your project config file you must restart your `recon` cli!
41 |
--------------------------------------------------------------------------------
/flow/lodash.js.flow:
--------------------------------------------------------------------------------
1 | declare module 'lodash' {
2 | declare function find(list: T[], predicate: (val: T)=>boolean): ?T;
3 | declare function findWhere(list: Array, properties: {[key:string]: any}): ?T;
4 | declare function clone(obj: T): T;
5 |
6 | declare function isEqual(a: any, b: any): boolean;
7 | declare function range(a: number, b: number): Array;
8 | declare function extend(o1: S, o2: T): S & T;
9 |
10 | declare function zip(a1: S[], a2: T[]): Array<[S, T]>;
11 |
12 | declare function flatten(a: S[][]): S[];
13 |
14 | declare function any(list: Array, pred: (el: T)=>boolean): boolean;
15 |
16 | declare function each(o: {[key:string]: T}, iteratee: (val: T, key: string)=>void): void;
17 | declare function each(a: T[], iteratee: (val: T, key: string)=>void): void;
18 |
19 | declare function map(a: T[], iteratee: (val: T, n?: number)=>U): U[];
20 | declare function map(a: {[key:K]: T}, iteratee: (val: T, k?: K)=>U): U[];
21 |
22 | declare function object(a: Array<[string, T]>): {[key:string]: T};
23 |
24 | declare function every(a: Array, pred: (val: T)=>boolean): boolean;
25 |
26 | declare function initial(a: Array, n?: number): Array;
27 | declare function rest(a: Array, index?: number): Array;
28 |
29 | declare function sortBy(a: T[], iteratee: (val: T)=>any): T[];
30 |
31 | declare function filter(o: {[key:string]: T}, pred: (val: T, k: string)=>boolean): T[];
32 |
33 | declare function isEmpty(o: any): boolean;
34 |
35 | declare function groupBy(a: Array, iteratee: (val: T, index: number)=>any): {[key:string]: T[]};
36 |
37 | declare function min(a: Array|{[key:any]: T}): T;
38 | declare function max(a: Array|{[key:any]: T}): T;
39 |
40 | declare function values(o: {[key: any]: T}): T[];
41 | declare function flatten(a: Array): Array;
42 |
43 | // TODO: improve this
44 | declare function chain(obj: S): any;
45 | }
46 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/utils/__tests__/isReactComponent.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node, jest */
2 | const Babylon = require('babylon');
3 | const traverse = require('babel-traverse').default;
4 |
5 | const isReactComponent = require('../isReactComponent');
6 |
7 | function parse(type, code) {
8 | let found;
9 |
10 | const ast = Babylon.parse(code, {
11 | plugins: ['jsx', 'flow', 'objectRestSpread'],
12 | });
13 |
14 | traverse(ast, {
15 | [type]: function find(path) {
16 | found = path.node;
17 | path.stop();
18 | },
19 | });
20 |
21 | return found;
22 | }
23 |
24 | describe('utils/react/isReactComponent', () => {
25 | it('should identify class components', () => {
26 | const node = parse(
27 | 'ClassDeclaration',
28 | `class MyComponent {
29 | render() {}
30 | }`
31 | );
32 | expect(isReactComponent(node)).toBe(true);
33 | });
34 |
35 | it('should identify function declarations', () => {
36 | const node = parse(
37 | 'FunctionDeclaration',
38 | `function MyComponent() {
39 | return Test
;
40 | }`
41 | );
42 | expect(isReactComponent(node)).toBe(true);
43 | });
44 |
45 | it('should identify function expressions', () => {
46 | const node = parse(
47 | 'FunctionExpression',
48 | `const MyComponent = function() {
49 | return Test
;
50 | }`
51 | );
52 | expect(isReactComponent(node)).toBe(true);
53 | });
54 |
55 | it('should identify arrow function expressions', () => {
56 | const node = parse(
57 | 'ArrowFunctionExpression',
58 | `const MyComponent = () => Test
;`
59 | );
60 | expect(isReactComponent(node)).toBe(true);
61 | });
62 |
63 | it('should NOT identify arrow function expressions without JSX', () => {
64 | const node = parse(
65 | 'ArrowFunctionExpression',
66 | `const MyComponent = () => true;`
67 | );
68 | expect(isReactComponent(node)).toBe(false);
69 | });
70 |
71 | it('should NOT identify function declarations without JSX', () => {
72 | const node = parse(
73 | 'FunctionDeclaration',
74 | `function MyComponent() {
75 | return null;
76 | }`
77 | );
78 | expect(isReactComponent(node)).toBe(false);
79 | });
80 | });
81 |
--------------------------------------------------------------------------------
/packages/recon-engine/docs/dev-guide.md:
--------------------------------------------------------------------------------
1 | recon-engine Developer Guide
2 | ============================
3 |
4 | As much help as we can cram into a md file to get you going developing Recon.
5 |
6 | Please also refer to our top-level [Developer Guide](../../../docs/dev-guide.md) if you haven't already!
7 |
8 | ## How do we come up with our data?
9 |
10 | 1. Discover
11 | 2. Parse and extract
12 | 2. Query and resolve
13 |
14 | #### 1. Discover
15 |
16 | The simplest way to build up a dependency and usage graph is to find and parse all
17 | modules in a codebase. The user can direct on where in their file system they want
18 | us to search.
19 |
20 | #### 2. Parse and extract
21 |
22 | We then, on an individual module basis, traverse and extract
23 | any information we can find to be potentially useful for querying later. This is
24 | basically taking the user's source code, identifying the pieces we want to query and
25 | then structuring it in the optimal way for search/traversal.
26 |
27 | i. Parse each module individually looking for *top level* symbols. Resolve each symbol
28 | to it's local definition.
29 | ii. Are any of these symbols components? Let's extract *whatever* useful info we can
30 | (and resolve references upto the module boundary).
31 | iii. Return "module" (containing root symbol table and corresponding component info)
32 | for it to be stored in global list.
33 |
34 | #### 3. Query and resolve
35 |
36 | i. Queries (Graphql) come in and we can traverse our parsed modules to fulfil.
37 | ii. As we are resolving references (mainly component usage) we can collect any useful
38 | information along the way (eg. "enhancements")
39 |
40 | > Note: Immutability helps this to be heavily optimised (memoizing)
41 |
42 | ## So what does that mean if there's something I want to fix?
43 |
44 | Well...
45 |
46 | - If Recon is struggling to extract component definitions in your module look in `src/parse`
47 | - If Recon is failing to connect the dots when you query components look in `src/query`
48 |
49 | ## Useful resources
50 |
51 | - [ASTExplorer](http://astexplorer.net) - Wonderful tool for easily inspecting your code's AST
52 | - [babel-handbook](https://github.com/thejameskyle/babel-handbook) (the plugin section) -
53 | If you want to touch `src/parse` this will get you up to speed with how to efficiently
54 | traverse the ast generated by babel.
55 |
56 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/engine/createEngine.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | const _glob = require('glob');
3 | const Path = require('path');
4 | const Jetpack = require('fs-jetpack');
5 | const {graphql} = require('graphql');
6 | const {
7 | pull,
8 | forEach,
9 | values,
10 | filter,
11 | map,
12 | memoize,
13 | join,
14 | flatten,
15 | cloneDeepWith,
16 | trim,
17 | } = require('lodash');
18 |
19 | const createSchema = require('../query/createSchema');
20 | const parseModule = require('../parse/parseModule');
21 |
22 | /** Promisified glob */
23 | function glob(pattern, opts) {
24 | return new Promise((resolve, reject) => {
25 | _glob(pattern, opts, (err, files) => {
26 | return err ? reject(err) : resolve(files);
27 | });
28 | });
29 | }
30 |
31 | /** Resolve modules based on configuration (allows for some level of rewriting module paths */
32 | function createResolver(
33 | cwd,
34 | {
35 | roots: _roots = [cwd],
36 | extensions = ['.js', '.jsx'],
37 | } = {}
38 | ) {
39 | // TODO: Support "aliases" (eg. webpack aliases)
40 | const roots = _roots.map(r => Path.resolve(cwd, r));
41 | return memoize(
42 | (context, target) => {
43 | const resolveFromPaths = [Path.dirname(context), ...roots];
44 | const resolvedPaths = resolveFromPaths.map(path =>
45 | Path.resolve(path, target));
46 | const finalPaths = /\.[a-zA-Z0-9]$/.test(target) // has extension
47 | ? resolvedPaths
48 | : flatten(
49 | resolvedPaths.map(p => [
50 | ...extensions.map(ext => `${p}${ext}`),
51 | Path.resolve(p, 'index.js'),
52 | ])
53 | );
54 |
55 | return finalPaths;
56 | },
57 | join
58 | );
59 | }
60 |
61 | /** Create a new engine instance */
62 | function createEngine(
63 | {
64 | files,
65 | context: _rawContext = '',
66 | cwd = process.cwd(),
67 | resolve,
68 | exclude = '/node_modules/',
69 | }
70 | ) {
71 | const subscriptions = [];
72 | const modules = {};
73 | let hasDiscovered = false;
74 | const excludeRegexp = new RegExp(trim(exclude, '/'));
75 | const context = Path.resolve(cwd, _rawContext);
76 |
77 | const resolveModulePaths = createResolver(context, resolve);
78 |
79 | // TODO: Cache parsed modules
80 | // TODO: Add persisted/watching support
81 |
82 | glob(files, {cwd: context}).then(rawFoundFiles => {
83 | hasDiscovered = true;
84 |
85 | const foundFiles = filter(rawFoundFiles, path => !excludeRegexp.test(path));
86 | forEach(foundFiles, file => {
87 | const path = Path.resolve(context, file);
88 | const module = {ready: false, file, path};
89 | modules[file] = module;
90 |
91 | Jetpack.readAsync(path, 'utf8').then(
92 | src => {
93 | module.ready = true;
94 | module.parsed = parseModule({src, path, id: file});
95 | module.error = module.parsed.error;
96 | send();
97 | },
98 | error => {
99 | module.ready = true;
100 | module.error = error;
101 | send();
102 | }
103 | );
104 | });
105 |
106 | send();
107 | });
108 |
109 | /** Get stats about the current state */
110 | function getStats() {
111 | const allModules = values(modules);
112 | const readyModules = filter(allModules, m => m.ready);
113 | const moduleErrors = map(filter(allModules, m => m.error), m => ({
114 | path: m.path,
115 | error: m.error,
116 | }));
117 | return {
118 | numModules: allModules.length,
119 | numReadyModules: readyModules.length,
120 | numErroredModules: moduleErrors.length,
121 | moduleErrors,
122 | hasDiscovered,
123 | canQuery: hasDiscovered && allModules.length === readyModules.length,
124 | };
125 | }
126 |
127 | // TODO: The memoizing inside query/resolve doesn't support changing data yet :(
128 | const schema = createSchema(modules, {resolveModulePaths});
129 |
130 | /* Run a graphql query against our store */
131 | function runQuery(query) {
132 | return graphql(schema, query);
133 | }
134 |
135 | /**
136 | * Push changes to subscribers
137 | */
138 | function send() {
139 | forEach(subscriptions, func => func(getStats()));
140 | }
141 |
142 | /** Subscribe to changes */
143 | function subscribe(func) {
144 | subscriptions.push(func);
145 | // return an unsubscribe function
146 | return () => {
147 | pull(subscriptions, [func]);
148 | };
149 | }
150 |
151 | /** get debug information */
152 | function _debug({raw = true}) {
153 | if (raw) {
154 | return {modules};
155 | }
156 |
157 | // exclude ast nodes from debug output (just track source location)
158 | const ignoreAstNodes = (v, k) => k === '__node' ? v.loc : undefined;
159 |
160 | const strippedModules = cloneDeepWith(modules, ignoreAstNodes);
161 | return {modules: strippedModules};
162 | }
163 |
164 | return {runQuery, subscribe, schema, _debug};
165 | }
166 |
167 | module.exports = createEngine;
168 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Recon
8 | =====
9 |
10 | Code Intelligence for React Applications.
11 |
12 | [](https://travis-ci.org/lystable/recon)
13 |
14 | ### What?
15 |
16 | Recon provides a new level of insight into your codebase allowing you to understand
17 | how your components are being used, easily grep their complexity, draw dependency graphs,
18 | and isolate points for optimisation.
19 |
20 | On top of this the raw information Recon provides gives a strong base for creating tools
21 | (such as living styleguides) which may need to plug in to component meta data.
22 |
23 | ### How?
24 |
25 | The core of Recon revolves around `recon-engine`. This engine parses your application pulling out
26 | any data which may be useful (eg. Props, component dependencies, enhancements etc.). Then a
27 | graphql query interface is exposed allowing you to explore your applications in an incredibly
28 | intuitive manner!
29 |
30 | Checking out our [test fixtures](./packages/recon-engine/src/engine/__fixtures__/) is a
31 | great place to an example of this.
32 |
33 | Once this data is consolidated the possibility of tools to be built on top are *endless*!
34 |
35 | Getting Started
36 | ---------------
37 |
38 | Prerequisites: `Node >v6`. Also ensure using `import/export` syntax, using JSX (see roadmap for full list)
39 |
40 | ### Install and configuration
41 |
42 | The quickest way to get going with Recon for your project is to use our CLI application.
43 |
44 | Firstly install with
45 |
46 | ```
47 | $ npm install -g recon-cli
48 | ```
49 |
50 | Now, within your application working directory, simply run
51 |
52 | ```
53 | $ recon
54 | ```
55 |
56 | You are now *inside* Recon! :O
57 |
58 | From this point forwards the entire power of Recon should be just a `help` command away.
59 |
60 | ```
61 | recon$ help
62 | ```
63 |
64 | The first thing you're going to want to do from here is create a new config file `.reconrc` in the working directory
65 | of your project.
66 |
67 | You can do this interactively by running
68 |
69 | ```
70 | recon$ init
71 | ```
72 |
73 | *To view all configuration possibilities you can view the docs [here](./packages/recon-config/README.md).*
74 |
75 | ### Show me the power!
76 |
77 | Why not start off by trying `stats`. This will analyse your application and dump out a bunch of objective
78 | statements and statistics.
79 |
80 | ```
81 | recon$ stats
82 | ```
83 |
84 | Then if you're feeling *extra* adventurous give `server` a go. This will spawn a new `graphql` server which will
85 | allow you to query your application meta data freely.
86 |
87 | ```
88 | recon$ server
89 | ```
90 |
91 | For everything else see what is available via the `help` command!
92 |
93 | ### I want to integrate Recon into x
94 |
95 | Documentation is going to be a little skimpy here for a while since we are planning on getting
96 | the internals of `recon-engine` to be as powerful as possible and stabilising the api as much as
97 | possible.
98 |
99 | Most likely you'll want to look at using `recon-engine` and `recon-server` (their tests are a decent
100 | place to start looking).
101 |
102 | > Disclaimer: This is a very early preview of Recon and you should expect breaking changes within the ({
44 | name: c.name,
45 | usages: c.dependants
46 | .map(d => d.usages.length)
47 | .reduce((a, b) => a + b, 0),
48 | }))
49 | .sort((a, b) => a.usages > b.usages ? -1 : 1)
50 | .map(c => [c.name, c.usages]),
51 | },
52 |
53 | {
54 | title: 'Fattest components',
55 | description: 'Which components render the most elements?',
56 | headers: ['Component Name', 'Rendered elements'],
57 | data: data.components
58 | .map(c => ({
59 | name: c.name,
60 | elements: sum(c.dependencies.map(d => d.usages.length)),
61 | }))
62 | .sort((a, b) => a.elements > b.elements ? -1 : 1)
63 | .map(c => [c.name, c.elements]),
64 | },
65 |
66 | {
67 | title: 'Most externally complex components',
68 | description: 'Which components require the most interface?',
69 | headers: ['Component Name', 'Average Props', 'Component Usages'],
70 | data: data.components
71 | .map(c => ({
72 | name: c.name,
73 | avgProps: round(
74 | mean(
75 | flatten(c.dependants.map(d => d.usages.map(u => u.props.length)))
76 | ),
77 | 2
78 | ),
79 | usages: sum(c.dependants.map(d => d.usages.length)),
80 | }))
81 | .sort((a, b) => a.avgProps > b.avgProps ? -1 : 1)
82 | .map(c => [c.name, c.avgProps, c.usages]),
83 | },
84 |
85 | {
86 | title: 'Most internally complex components',
87 | description: 'Which components deal with the most amount of unique dependencies?',
88 | headers: ['Component Name', 'Unique Dependencies'],
89 | data: data.components
90 | .map(c => ({
91 | name: c.name,
92 | uniqueDeps: c.dependencies.length,
93 | }))
94 | .sort((a, b) => a.uniqueDeps > b.uniqueDeps ? -1 : 1)
95 | .map(c => [c.name, c.uniqueDeps]),
96 | },
97 |
98 | {
99 | title: 'Dead components',
100 | description: 'Which components are never referenced?',
101 | headers: ['Component Name'],
102 | data: data.components
103 | .filter(c => !c.dependants.length && c.name)
104 | .map(c => [c.name]),
105 | },
106 |
107 | {
108 | title: 'One trick ponies (internal)',
109 | description: 'Which components are only ever used once?',
110 | headers: ['Component Name'],
111 | data: data.components
112 | .filter(
113 | c =>
114 | c.dependants.length === 1 &&
115 | c.module.path === c.dependants[0].component.module.path
116 | )
117 | .map(c => [c.name]),
118 | },
119 |
120 | {
121 | title: 'One trick ponies (external)',
122 | description: 'Which components are only ever used once and imported from an external module?',
123 | headers: ['Component Name'],
124 | data: data.components
125 | .filter(
126 | c =>
127 | c.dependants.length === 1 &&
128 | c.module.path !== c.dependants[0].component.module.path
129 | )
130 | .map(c => [c.name]),
131 | },
132 |
133 | {
134 | title: 'Favourite prop names',
135 | description: 'Which prop names are most popular in usage?',
136 | headers: ['Prop name', 'Usages'],
137 | data: toPairs(
138 | groupBy(
139 | flattenDeep(
140 | data.components.map(c =>
141 | c.dependencies.map(d =>
142 | d.usages.map(u => u.props.map(p => p.name))))
143 | ),
144 | identity
145 | )
146 | )
147 | .map(([name, u]) => ({name, usages: u.length}))
148 | .sort((a, b) => a.usages > b.usages ? -1 : 1)
149 | .map(c => [c.name, c.usages]),
150 | },
151 |
152 | {
153 | debug: true, // only show in debug mode
154 | title: 'Unresolved dependencies',
155 | description: 'Usages where the component definition was not found',
156 | headers: ['Parent Component', 'Dependency Name'],
157 | data: flatMap(data.components, c =>
158 | c.dependencies.filter(dep => !dep.component).map(dep => ({
159 | depName: dep.name,
160 | parent: c.id,
161 | }))).map(c => [c.parent, c.depName]),
162 | },
163 | ];
164 | }
165 |
166 | module.exports = makeStats;
167 |
--------------------------------------------------------------------------------
/packages/recon-cli/src/index.js:
--------------------------------------------------------------------------------
1 | #! /usr/bin/env node
2 | const vorpal = require('vorpal')();
3 | const {
4 | forEach,
5 | padEnd,
6 | isArray,
7 | map,
8 | join,
9 | take,
10 | max,
11 | memoize,
12 | has,
13 | } = require('lodash');
14 | const ProgressBar = require('progress');
15 | const dedent = require('dedent');
16 | const jetpack = require('fs-jetpack');
17 | const Path = require('path');
18 |
19 | const {
20 | getConfig: _getConfig,
21 | createConfig: _createConfig,
22 | configFromWebpack: _configFromWebpack,
23 | } = require('recon-config');
24 | const {createEngine} = require('recon-engine');
25 | const {pullStats: _pullStats} = require('recon-stats');
26 | const {createServer} = require('recon-server');
27 |
28 | const chalk = vorpal.chalk;
29 |
30 | // helpful urls
31 | const CONFIG_HELP_URL = 'https://github.com/lystable/recon/tree/master/packages/recon-config';
32 |
33 | // ----------------------------------------------------------------------------
34 | // Configuration
35 | // ----------------------------------------------------------------------------
36 |
37 | /** Determine whether the user may be using webpack or not? */
38 | const detectWebpack = () => {
39 | const pkg = jetpack.cwd(process.cwd()).read('package.json', 'json');
40 | return has(pkg.dependencies, 'webpack') ||
41 | has(pkg.devDependencies, 'webpack');
42 | };
43 |
44 | /** Given path to webpack config file lets gen recon config */
45 | const configFromWebpack = path => {
46 | const configPath = Path.resolve(process.cwd(), path);
47 | const webpackConfig = require(configPath); // eslint-disable-line global-require, import/no-dynamic-require
48 | return _configFromWebpack(webpackConfig);
49 | };
50 |
51 | /** Current project config */
52 | const getConfig = uc =>
53 | new Promise(accept => accept(_getConfig(uc))).catch(() => {
54 | // Looks like we need a config file...
55 | const act = vorpal.activeCommand;
56 | act.log(chalk.red('Oops! Looks like we failed to load any configuration.'));
57 |
58 | /* eslint-disable no-use-before-define */
59 | return makeConfig().catch(
60 | /* eslint-enable no-use-before-define */
61 | () => {
62 | throw new Error('We need a configuration file to continue! :(');
63 | }
64 | );
65 | });
66 |
67 | const makeConfig = () => {
68 | const act = vorpal.activeCommand;
69 |
70 | return act
71 | .prompt([
72 | {
73 | type: 'confirm',
74 | name: 'create',
75 | message: 'Would you like us to create a config file for you?',
76 | },
77 | {
78 | type: 'confirm',
79 | name: 'webpack',
80 | message: "We detected you're using webpack. Would you like us to try and generate resolve config from there?",
81 | when: ({create}) => create && detectWebpack(),
82 | },
83 | {
84 | type: 'input',
85 | name: 'webpackConfig',
86 | message: 'What webpack config file should we use for your configuration? (relative to cwd)',
87 | default: './webpack.config.js',
88 | when: ({webpack}) => webpack,
89 | validate: path =>
90 | jetpack.exists(path) === 'file' || 'Could not find that file.',
91 | },
92 | {
93 | type: 'input',
94 | name: 'files',
95 | message: 'What modules should we parse in your application? (glob pattern, relative to context)',
96 | default: '**/!(*.test|*.manifest).js*',
97 | when: ({create}) => create,
98 | },
99 | ])
100 | .then(result => {
101 | const {create, files, webpack, webpackConfig} = result;
102 |
103 | if (create) {
104 | const config = Object.assign(
105 | {files},
106 | webpack ? configFromWebpack(webpackConfig) : {}
107 | );
108 | const file = _createConfig(config);
109 | act.log(chalk.green(`Configuration file created! ${file}`));
110 | act.log(
111 | chalk.dim(
112 | `Read more about .reconrc configuration here: ${CONFIG_HELP_URL}`
113 | )
114 | );
115 | // anddd, try again...
116 | return getConfig();
117 | }
118 |
119 | return null;
120 | });
121 | };
122 |
123 | vorpal
124 | .command('init', 'Initialise recon for this project. Creates config etc.')
125 | .action(makeConfig);
126 |
127 | // ----------------------------------------------------------------------------
128 | // Engine Management
129 | // ----------------------------------------------------------------------------
130 |
131 | /** Get a (persisted) recon engine for current project */
132 | const getEngine = memoize(() =>
133 | getConfig().then(
134 | config =>
135 | new Promise(accept => {
136 | const act = vorpal.activeCommand;
137 | act.log('Starting Recon Engine...');
138 | const createdEngine = createEngine(config);
139 | let hasLoggedDiscovered = false;
140 | let bar;
141 |
142 | createdEngine.subscribe(stats => {
143 | if (!hasLoggedDiscovered && stats.hasDiscovered) {
144 | act.log(`Discovered ${stats.numModules} modules. Parsing...`);
145 | hasLoggedDiscovered = true;
146 | // TODO: right way to do progress bars in vorpal? https://github.com/dthree/vorpal/issues/176
147 | bar = new ProgressBar('parsing [:bar] :percent :etas', {
148 | complete: '=',
149 | incomplete: ' ',
150 | width: 30,
151 | total: stats.numModules,
152 | clear: true,
153 | });
154 | }
155 | if (bar) {
156 | bar.update(
157 | stats.numReadyModules
158 | ? stats.numReadyModules / stats.numModules
159 | : 0
160 | );
161 | }
162 | if (stats.canQuery) {
163 | act.log(`Parsed ${stats.numModules} modules.`);
164 | if (stats.numErroredModules) {
165 | act.log('');
166 | act.log(
167 | chalk.bold(
168 | `Saw ${stats.numErroredModules} errors while parsing:`
169 | )
170 | );
171 | map(stats.moduleErrors, (m, i) =>
172 | act.log(chalk.red(`${i + 1}. ${m.error.message} <${m.path}>`)));
173 | act.log('');
174 | }
175 | accept(createdEngine);
176 | }
177 | });
178 | })
179 | ));
180 |
181 | // ----------------------------------------------------------------------------
182 | // Statistics
183 | // ----------------------------------------------------------------------------
184 |
185 | /** Given recon stats, dump them to the user */
186 | function logStats(stats, {numRows = 20, debug = false} = {}) {
187 | const act = vorpal.activeCommand;
188 | const SEP = ' | ';
189 | act.log('');
190 | forEach(stats.filter(s => debug ? true : !s.debug), stat => {
191 | act.log(chalk.bold(`${stat.debug ? '[DEBUG] ' : ''}${stat.title}`));
192 | act.log(chalk.italic.dim(stat.description));
193 | act.log('');
194 | const displayRows = isArray(stat.data)
195 | ? take(stat.data, parseInt(numRows, 10))
196 | : [];
197 | const colWidths = stat.headers
198 | ? stat.headers.map((h, i) =>
199 | max([h.length, ...map(displayRows, l => `${l[i]}`.length)]))
200 | : [];
201 | if (stat.headers) {
202 | act.log(
203 | join(
204 | map(stat.headers, (h, i) => chalk.bold(padEnd(h, colWidths[i]))),
205 | SEP
206 | )
207 | );
208 | }
209 | if (isArray(stat.data)) {
210 | forEach(displayRows, l =>
211 | act.log(join(map(l, (v, i) => padEnd(`${v}`, colWidths[i])), SEP)));
212 | const numHiddenLines = stat.data.length - displayRows.length;
213 | if (numHiddenLines > 0) {
214 | act.log('');
215 | act.log(`& ${numHiddenLines} more rows ...`);
216 | }
217 | } else {
218 | act.log(stat.data);
219 | }
220 | act.log('');
221 | act.log('---');
222 | act.log('');
223 | });
224 | }
225 |
226 | /** Given a "ready to query" engine lets pull some stats */
227 | function pullStats(engine) {
228 | vorpal.activeCommand.log('Querying and pulling stats...');
229 | return _pullStats(engine);
230 | }
231 |
232 | vorpal
233 | .command('stats', 'Prints statistics about your React application')
234 | .option('--numRows', 'Max number of rows to display within printed stats')
235 | .option('--debug', 'Output debug stats')
236 | .action(args =>
237 | getEngine().then(pullStats).then(s => logStats(s, args.options)));
238 |
239 | // ----------------------------------------------------------------------------
240 | // Server
241 | // ----------------------------------------------------------------------------
242 |
243 | /** Current running server */
244 | let runningServer = null;
245 |
246 | /** Create a new server */
247 | function spawnServer(engine, opts) {
248 | if (runningServer) {
249 | return runningServer;
250 | }
251 | const act = vorpal.activeCommand;
252 | act.log('Spawning server...');
253 | return createServer(engine, opts).then(server => {
254 | runningServer = server;
255 | const port = server.address().port;
256 | act.log('');
257 | act.log(
258 | dedent`
259 | Recon server listening on port ${port}!
260 | Visit ${chalk.bold(`http://localhost:${port}/graphql`)} to play with your data!
261 | `
262 | );
263 | act.log('');
264 | return server;
265 | });
266 | }
267 |
268 | /** Create a new server */
269 | function killServer() {
270 | if (!runningServer) {
271 | return;
272 | }
273 | runningServer.close();
274 | vorpal.activeCommand.log('Server stopped');
275 | runningServer = null;
276 | }
277 |
278 | vorpal
279 | .command('server start', 'Spawn a server which accepts graphql queries')
280 | .alias('server')
281 | .option('-p --port', 'Port to run the server on')
282 | .action(args => getEngine().then(e => spawnServer(e, args.options)));
283 |
284 | vorpal
285 | .command('server stop', 'Kill the current recon server')
286 | .alias('server kill')
287 | .action(() => killServer());
288 |
289 | // ----------------------------------------------------------------------------
290 | // Debug
291 | // ----------------------------------------------------------------------------
292 |
293 | /** Dump data from engine to disk */
294 | function dumpDebug(engine, {file = 'recon-dump.json'}) {
295 | return _pullStats(engine).then(stats => {
296 | vorpal.activeCommand.log('Dumping debug information...');
297 | const data = {stats, store: engine._debug({raw: false})};
298 | jetpack.write(file, data, {jsonIndent: 0});
299 | const path = Path.resolve(process.cwd(), file);
300 | vorpal.activeCommand.log(`Dumped successfully to ${path}`);
301 | });
302 | }
303 |
304 | vorpal
305 | .command('dump', 'Dump debug information')
306 | .option('-f --file', 'File to dump to')
307 | .action(args => getEngine().then(e => dumpDebug(e, args.options)));
308 |
309 | // final setup - either user wants interactive mode or is just running a command
310 | const parsedArgs = vorpal.parse(process.argv, {use: 'minimist'});
311 | if (!parsedArgs._) {
312 | // TODO: display working project? Ie. recon:my-app$
313 | vorpal.delimiter('recon$').show();
314 | } else {
315 | vorpal.parse(parsedArgs._);
316 | }
317 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/query/createSchema.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-use-before-define */
2 | const {
3 | GraphQLSchema,
4 | GraphQLObjectType,
5 | GraphQLString,
6 | GraphQLList,
7 | } = require('graphql');
8 |
9 | // TODO: Roll in graphql-relay to make handling connections nicer
10 |
11 | const {
12 | flatten,
13 | map,
14 | groupBy,
15 | values,
16 | find,
17 | last,
18 | memoize,
19 | join,
20 | filter,
21 | flatMap,
22 | isString,
23 | } = require('lodash');
24 |
25 | const makeDOMComponent = memoize(name => {
26 | // TODO: We should *probably* have resolved these within parse when we see a dom reference?
27 | return {
28 | id: `__REACT_DOM::${name}`,
29 | name,
30 | node: null,
31 | enhancements: [],
32 | props: [], // TODO: Probably a standard definition somewhere of dom attributes?
33 | deps: [],
34 | definedIn: null,
35 | };
36 | });
37 |
38 | function createSchema(dataSource, {resolveModulePaths}) {
39 | // TODO: Need to invalidate memoizing as modules are re-parsed (ie. support persisted engine)
40 |
41 | // RESOLUTION ---------------------------------------------------------------
42 |
43 | /** Get data for query/resolution stage */
44 | const getModules = memoize(() => {
45 | return map(filter(values(dataSource), m => m.ready), m => m.parsed);
46 | });
47 |
48 | const allComponents = memoize(() => {
49 | return filter(flatten(map(getModules(), m => m.data.components)), c => !!c);
50 | });
51 |
52 | const getModule = memoize(
53 | paths => {
54 | return find(getModules(), m => find(paths, path => path === m.path));
55 | },
56 | p => join(p)
57 | );
58 |
59 | const resolveSymbol = memoize(
60 | (name, module) => {
61 | const localSymbol = module.data.symbols.find(s => s.name === name);
62 |
63 | if (!localSymbol) {
64 | return {
65 | name,
66 | module,
67 | notFound: true,
68 | };
69 | }
70 |
71 | if (localSymbol.type.type === 'Identifier') {
72 | return resolveSymbol(localSymbol.type.__node.name, module);
73 | }
74 |
75 | if (localSymbol.type.type === 'ImportSpecifier') {
76 | const nextModule = getModule(
77 | resolveModulePaths(module.path, localSymbol.type.source)
78 | );
79 |
80 | if (!nextModule) {
81 | return {
82 | name,
83 | module,
84 | notFound: true,
85 | };
86 | }
87 |
88 | return resolveSymbol(
89 | `export::${localSymbol.type.sourceName}`,
90 | nextModule
91 | );
92 | }
93 |
94 | if (localSymbol.type.type === 'ImportDefaultSpecifier') {
95 | const nextModule = getModule(
96 | resolveModulePaths(module.path, localSymbol.type.source)
97 | );
98 |
99 | if (!nextModule) {
100 | return {
101 | name,
102 | module,
103 | notFound: true,
104 | };
105 | }
106 |
107 | return resolveSymbol('export::default', nextModule);
108 | }
109 |
110 | if (localSymbol.type.type === 'ExportSpecifier') {
111 | const nextModule = getModule(
112 | resolveModulePaths(module.path, localSymbol.type.source)
113 | );
114 |
115 | if (!nextModule) {
116 | return {
117 | name,
118 | module,
119 | notFound: true,
120 | };
121 | }
122 |
123 | return resolveSymbol(
124 | `export::${localSymbol.type.sourceName}`,
125 | nextModule
126 | );
127 | }
128 |
129 | return {
130 | name,
131 | module,
132 | };
133 | },
134 | (n, m) => n + m.path
135 | );
136 |
137 | const getComponentFromResolvedSymbol = memoize(
138 | resolvedSymbol => {
139 | const component = find(
140 | resolvedSymbol.module.data.components,
141 | c => c.name === resolvedSymbol.name
142 | );
143 |
144 | if (component) {
145 | return component;
146 | }
147 |
148 | const componentPath = find(
149 | resolvedSymbol.module.data.potentialComponentPaths,
150 | cp => cp.name === resolvedSymbol.name
151 | );
152 |
153 | // absolutely no paths :(
154 | if (!componentPath) {
155 | return null;
156 | }
157 |
158 | // Only taking the *last* potential component here. Really we should be
159 | // able to offer all of them as potential components Ie. branching
160 | const target = last(componentPath.targets);
161 | const resolvedComponent = resolveComponentByName(
162 | target.name,
163 | resolvedSymbol.module
164 | );
165 |
166 | // Does this break things by being path specific return value? (ie. due to aggressive memoizing)
167 | // Maybe not since within this module the given symbol would always have the same enhancement path.
168 | return Object.assign({}, resolvedComponent, {
169 | pathEnhancements: componentPath.enhancements,
170 | });
171 | },
172 | s => s.name + s.module.path
173 | );
174 |
175 | const resolveComponentByName = memoize(
176 | (name, module) => {
177 | // JSX Convention says if the identifier begins lowercase it is
178 | // a dom node rather than a custom component
179 | if (/^[a-z][a-z0-9]*/.test(name)) {
180 | return makeDOMComponent(name);
181 | }
182 |
183 | const symbol = resolveSymbol(name, module);
184 |
185 | if (symbol.notFound) {
186 | return null;
187 | }
188 |
189 | return getComponentFromResolvedSymbol(symbol) || null;
190 | },
191 | (n, m) => n + m.path
192 | );
193 |
194 | const resolveComponent = memoize(
195 | (component, module) => {
196 | // TODO: Need to track/resolve enhancement paths via usage
197 |
198 | const resolvedDeps = map(
199 | values(groupBy(component.deps, 'name')),
200 | usages => {
201 | const resolvedComponent = resolveComponentByName(
202 | usages[0].name,
203 | module
204 | );
205 |
206 | return {
207 | name: usages[0].name,
208 | component: resolvedComponent,
209 | byComponent: component,
210 | usages: map(usages, u =>
211 | Object.assign({}, u, {
212 | component: resolvedComponent,
213 | byComponent: component,
214 | })),
215 | };
216 | }
217 | );
218 |
219 | return Object.assign({}, component, {
220 | resolvedDeps,
221 | });
222 | },
223 | (c, m) => c.id + m.path
224 | );
225 |
226 | const allResolvedComponents = memoize(() => {
227 | return flatten(
228 | getModules().map(module =>
229 | module.data.components.map(component =>
230 | resolveComponent(component, module)))
231 | );
232 | });
233 |
234 | const resolveComponentDependants = memoize(
235 | component => {
236 | const all = allResolvedComponents();
237 |
238 | return flatten(
239 | all
240 | .filter(c =>
241 | c.resolvedDeps.find(
242 | depC => depC.component && depC.component.id === component.id
243 | ))
244 | .map(c =>
245 | c.resolvedDeps
246 | .filter(
247 | depC => depC.component && depC.component.id === component.id
248 | )
249 | .map(depC => Object.assign({}, depC, {component: c})))
250 | );
251 | },
252 | c => c.id
253 | );
254 |
255 | // SCHEMA -------------------------------------------------------------------
256 |
257 | const moduleType = new GraphQLObjectType({
258 | name: 'ModuleType',
259 | fields: () => ({
260 | path: {type: GraphQLString},
261 | }),
262 | });
263 |
264 | const propUsageType = new GraphQLObjectType({
265 | name: 'PropUsageType',
266 | fields: () => ({
267 | name: {type: GraphQLString},
268 | valueType: {
269 | type: GraphQLString,
270 | resolve: prop => prop.type.type,
271 | },
272 | }),
273 | });
274 |
275 | const componentUsageType = new GraphQLObjectType({
276 | name: 'ComponentUsageType',
277 | fields: () => ({
278 | name: {type: GraphQLString},
279 | component: {type: componentType},
280 | byComponent: {type: componentType},
281 | props: {type: new GraphQLList(propUsageType)},
282 | }),
283 | });
284 |
285 | const componentDependencyType = new GraphQLObjectType({
286 | name: 'ComponentDependencyType',
287 | fields: () => ({
288 | name: {type: GraphQLString},
289 | component: {type: componentType},
290 | usages: {type: new GraphQLList(componentUsageType)},
291 | }),
292 | });
293 |
294 | const componentEnhancementType = new GraphQLObjectType({
295 | // TODO: Enhancements need a lot of work in general. need to decide what useful information we can provide
296 | name: 'ComponentEnhancementType',
297 | fields: () => ({
298 | type: {type: GraphQLString},
299 | callee: {
300 | type: new GraphQLObjectType({
301 | name: 'EnhanceCallee',
302 | fields: () => ({
303 | type: {type: GraphQLString},
304 | name: {type: GraphQLString},
305 | }),
306 | }),
307 | },
308 | }),
309 | });
310 |
311 | const componentType = new GraphQLObjectType({
312 | name: 'ComponentType',
313 | fields: () => ({
314 | id: {type: GraphQLString},
315 | name: {type: GraphQLString},
316 | dependencies: {
317 | type: new GraphQLList(componentDependencyType),
318 | resolve: component => {
319 | const all = allResolvedComponents();
320 |
321 | return find(all, c => c.id === component.id).resolvedDeps;
322 | },
323 | },
324 | dependants: {
325 | type: new GraphQLList(componentDependencyType),
326 | resolve: resolveComponentDependants,
327 | },
328 | usages: {
329 | type: new GraphQLList(componentUsageType),
330 | resolve: component => {
331 | return flatMap(
332 | resolveComponentDependants(component),
333 | dependant => dependant.usages
334 | );
335 | },
336 | },
337 | enhancements: {
338 | type: new GraphQLList(componentEnhancementType),
339 | },
340 | pathEnhancements: {
341 | description: 'Contextual enhancements',
342 | type: new GraphQLList(componentEnhancementType),
343 | },
344 | module: {
345 | type: moduleType,
346 | resolve: component =>
347 | getModules().find(m => m.path === component.definedIn),
348 | },
349 | }),
350 | });
351 |
352 | const schemaType = new GraphQLSchema({
353 | query: new GraphQLObjectType({
354 | name: 'RootQueryType',
355 | fields: () => ({
356 | components: {
357 | type: new GraphQLList(componentType),
358 | args: {
359 | search: {
360 | type: GraphQLString,
361 | },
362 | },
363 | resolve(root, {search}) {
364 | const all = allComponents();
365 |
366 | if (search) {
367 | return all.filter(
368 | c => isString(c.name) && c.name.indexOf(search) > -1
369 | );
370 | }
371 |
372 | return all;
373 | },
374 | },
375 | component: {
376 | type: componentType,
377 | args: {
378 | name: {
379 | type: GraphQLString,
380 | },
381 | id: {
382 | type: GraphQLString,
383 | },
384 | },
385 | resolve(root, {name, id}) {
386 | const all = allComponents();
387 |
388 | if (id) {
389 | return all.find(c => c.id === id) || null;
390 | }
391 |
392 | return all.find(c => c.name === name) || null;
393 | },
394 | },
395 | modules: {
396 | type: new GraphQLList(moduleType),
397 | resolve() {
398 | return getModules();
399 | },
400 | },
401 | module: {
402 | type: moduleType,
403 | args: {
404 | path: {
405 | type: GraphQLString,
406 | },
407 | },
408 | resolve(root, {path}) {
409 | const all = getModules();
410 |
411 | return all.find(c => c.path === path) || null;
412 | },
413 | },
414 | numComponents: {
415 | // TODO: move into better "components" shape
416 | type: GraphQLString,
417 | resolve() {
418 | return allComponents().length;
419 | },
420 | },
421 | }),
422 | }),
423 | });
424 |
425 | return schemaType;
426 | }
427 |
428 | module.exports = createSchema;
429 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/parse/__tests__/__fixtures__/real-world-lystable/src.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 | import PropTypes from 'utils/prop-types';
4 | import {compose, withReducer, branch} from 'recompose';
5 | import {identity} from 'lodash';
6 | import {isRecruitmentManager} from 'utils/talent';
7 | import {TALENT_REQUEST_STATES} from 'constants/talent';
8 | import {TalentRequest, Agency, AgencyTalentRequest} from 'api/records';
9 | import {createContainer, query as q} from 'api/recall';
10 | import DateRange from 'moment-range';
11 | import {PRIVACY_MODES} from 'constants/notes';
12 | import {matchRecord} from 'utils/record';
13 | import {Record} from 'immutable';
14 | import withStaticProperties from 'decorators/with-static-properties';
15 | import notFound from 'decorators/not-found';
16 |
17 | import {Box, Flex} from 'components/layout';
18 | import Paper from 'components/paper';
19 | import LoadingSpinner from 'components/loading-spinner';
20 | import SectionHeader from 'components/section-header';
21 | import CardHeader from 'components/card-header';
22 | import Link from 'components/link';
23 | import Text from 'components/text';
24 | import Icon from 'components/icon';
25 | import CandidateList from 'components/candidate-list';
26 | import MenuChecklist from 'components/menu-checklist';
27 | import ContextualMenuButton from 'components/contextual-menu-button';
28 | import MenuItemWithConfirm from 'components/menu-item-with-confirm';
29 | import TalentRequestInformation from 'components/talent-request-information';
30 | import NotesCard from 'components/notes-card';
31 | import Avatar from 'components/avatar';
32 | import Button from 'components/button';
33 | import Modal from 'components/modal';
34 | import TalentRequestForm from 'hera/components/talent-request-form';
35 |
36 | import withViewer from 'decorators/with-viewer';
37 | import withActions from 'decorators/with-actions';
38 | import {
39 | updateTalentRequest,
40 | cancelTalentRequest,
41 | setFinalCandidate,
42 | removeCandidate,
43 | createAgencyTalentRequest,
44 | saveTalentRequest,
45 | } from 'actions/talent-request-actions';
46 |
47 | // State
48 |
49 | export const State = new Record({
50 | editing: false,
51 | });
52 |
53 | // Actions
54 |
55 | const TOGGLE_EDIT_FORM = 'TOGGLE_EDIT_FORM';
56 | const CLOSE_EDIT_FORM = 'CLOSE_EDIT_FORM';
57 |
58 | export const reducer = (state, action) => {
59 | switch (action.type) {
60 | case TOGGLE_EDIT_FORM:
61 | return state.merge({editing: !state.editing});
62 |
63 | case CLOSE_EDIT_FORM:
64 | return state.merge({editing: false});
65 |
66 | default:
67 | return state;
68 | }
69 | };
70 |
71 | // View
72 |
73 | /* Render talent reqiest updates */
74 | export function UpdatesCard(
75 | {
76 | talentRequest,
77 | ...otherProps
78 | }
79 | ) {
80 | return (
81 |
82 |
83 |
84 |
85 | {!!talentRequest.final_candidate
86 | ?
87 |
88 |
92 |
93 |
94 | Selected Candidate
95 | {talentRequest.final_candidate.supplier.name}
96 |
97 |
98 | : null}
99 |
100 |
101 |
102 |
103 | {talentRequest.candidates.size}
104 |
105 |
106 | Candidates
107 |
108 |
109 |
110 |
111 |
112 |
113 | {talentRequest.agencies.size}
114 |
115 |
116 | Agencies
117 |
118 |
119 |
120 |
121 | );
122 | }
123 |
124 | export function AgencyChecklist(
125 | {
126 | talentRequest,
127 | agencies,
128 | onCreated,
129 | createAgencyTalentRequestAction,
130 | }
131 | ) {
132 | const items = agencies.map(agency => {
133 | // Check if the agency is already attached
134 | const existingAgency = talentRequest.agencies.find(
135 | _agency => !!_agency && matchRecord(agency, _agency)
136 | );
137 |
138 | return {
139 | checked: !!existingAgency,
140 | label: agency.name,
141 | checkAction: () => {
142 | createAgencyTalentRequestAction(
143 | new AgencyTalentRequest({
144 | talent_request: talentRequest,
145 | agency,
146 | })
147 | ).then(() => {
148 | onCreated();
149 | });
150 | },
151 | };
152 | });
153 |
154 | return (
155 |
160 |
161 | Add to Talent Request
162 |
163 |
164 | );
165 | }
166 |
167 | const Z_INDEX = {
168 | MODAL: 200,
169 | };
170 |
171 | /**
172 | * Display a talent request in detail
173 | */
174 | export const TalentRequestsDetailPage = withStaticProperties({
175 | propTypes: {
176 | talentRequest: PropTypes.record(TalentRequest),
177 | agencies: PropTypes.iterableOf(PropTypes.record(Agency)),
178 | recall: PropTypes.shape({
179 | markAsStale: PropTypes.func,
180 | }).isRequired,
181 | queries: PropTypes.shape({
182 | agencies: PropTypes.shape({
183 | id: PropTypes.string,
184 | ready: PropTypes.bool,
185 | }),
186 | talentRequest: PropTypes.shape({
187 | id: PropTypes.string,
188 | ready: PropTypes.bool,
189 | }),
190 | }).isRequired,
191 | viewer: PropTypes.viewer.isRequired,
192 | updateTalentRequest: PropTypes.func.isRequired,
193 | cancelTalentRequest: PropTypes.func.isRequired,
194 | setFinalCandidate: PropTypes.func.isRequired,
195 | removeCandidate: PropTypes.func.isRequired,
196 | createAgencyTalentRequest: PropTypes.func.isRequired,
197 | saveTalentRequest: PropTypes.func.isRequired,
198 | state: PropTypes.shape({
199 | editing: PropTypes.bool.isRequired,
200 | }).isRequired,
201 | dispatch: PropTypes.func.isRequired,
202 | },
203 | })(function TalentRequestsDetailPage(props) {
204 | const {
205 | talentRequest,
206 | agencies,
207 | queries,
208 | viewer,
209 | // withReducer
210 | state: {editing},
211 | dispatch,
212 | } = props;
213 |
214 | const handleContainerRefresh = () => {
215 | props.recall.markAsStale([
216 | props.queries.agencies.id,
217 | props.queries.talentRequest.id,
218 | ]);
219 | };
220 |
221 | const fire = action => () => dispatch(action);
222 |
223 | const status = !!talentRequest
224 | ? TALENT_REQUEST_STATES[talentRequest.status]
225 | : null;
226 |
227 | const searchRange = !!talentRequest &&
228 | !!talentRequest.start_date &&
229 | !!talentRequest.end_date
230 | ? new DateRange(talentRequest.start_date, talentRequest.end_date)
231 | : null;
232 |
233 | const heading = (
234 |
235 | {isRecruitmentManager(viewer)
236 | ?
237 | Talent Requests
238 |
239 | :
240 | My Requests
241 | }
242 | chevron_right
243 | {!!talentRequest ? talentRequest.job_title : 'Loading'}
244 |
245 | );
246 |
247 | const menu = (
248 |
249 |
255 | props.cancelTalentRequest(talentRequest)}
259 | key="cancel"
260 | >
261 | Cancel Request
262 |
263 |
264 | );
265 |
266 | const editTalentRequest = [
267 | ,
275 |
276 |
282 |
289 | ,
290 | ];
291 |
292 | return (
293 |
294 | {queries.talentRequest.ready
295 | ?
296 |
297 |
298 |
299 |
310 |
311 |
315 |
316 |
317 |
318 |
319 |
320 |
325 |
326 |
327 |
328 |
333 |
342 |
343 |
344 | : }
345 |
346 | );
347 | });
348 |
349 | const candidateFragment = {
350 | id: true,
351 | removed_at: true,
352 | removed_by: {
353 | id: true,
354 | },
355 | talent_request: {
356 | id: true,
357 | },
358 | supplier: {
359 | id: true,
360 | name: true,
361 | email: true,
362 | city: true,
363 | next_available: true,
364 | show_availability: true,
365 | supplier_type: true,
366 | picture: {
367 | id: true,
368 | type: true,
369 | remote_id: true,
370 | filename: true,
371 | url: true,
372 | },
373 | profile: {
374 | id: true,
375 | contact_email: true,
376 | accepted: true,
377 | invited_by: {
378 | id: true,
379 | name: true,
380 | },
381 | created_at: true,
382 | created_by: {
383 | id: true,
384 | name: true,
385 | },
386 | approved_at: true,
387 | contact_name: true,
388 | team: {
389 | id: true,
390 | },
391 | agency: {
392 | id: true,
393 | name: true,
394 | contact_name: true,
395 | email: true,
396 | },
397 | },
398 | },
399 | };
400 |
401 | export const container = createContainer({
402 | queries: {
403 | agencies: q.many(Agency, {
404 | params: () => ({
405 | filter: {
406 | archived: false,
407 | },
408 | }),
409 | fields: {
410 | name: true,
411 | contact_name: true,
412 | },
413 | }),
414 | talentRequest: q.single(TalentRequest, {
415 | params: vars => ({
416 | id: vars.params.requestId,
417 | }),
418 | fields: {
419 | id: true,
420 | created_at: true,
421 | status: true,
422 | submitted_by: {
423 | id: true,
424 | name: true,
425 | picture: {
426 | id: true,
427 | type: true,
428 | remote_id: true,
429 | filename: true,
430 | url: true,
431 | },
432 | },
433 | job_title: true,
434 | job_description: true,
435 | position_type: true,
436 | start_date: true,
437 | end_date: true,
438 | location: true,
439 | team_name: true,
440 | urgency: true,
441 | skills: {
442 | edges: {
443 | id: true,
444 | type: true,
445 | name: true,
446 | },
447 | },
448 | final_candidate: {
449 | ...candidateFragment,
450 | },
451 | candidates: {
452 | edges: {
453 | ...candidateFragment,
454 | },
455 | },
456 | agencies: {
457 | edges: {
458 | id: true,
459 | name: true,
460 | contact_name: true,
461 | email: true,
462 | },
463 | },
464 | },
465 | }),
466 | },
467 | });
468 |
469 | const talentRequestOrNotFound = branch(
470 | ({queries, talentRequest}) => !queries.talentRequest.ready || !!talentRequest,
471 | identity,
472 | notFound()
473 | );
474 |
475 | export default compose(
476 | withViewer(),
477 | withActions({
478 | updateTalentRequest,
479 | cancelTalentRequest,
480 | setFinalCandidate,
481 | removeCandidate,
482 | createAgencyTalentRequest,
483 | saveTalentRequest,
484 | }),
485 | container,
486 | talentRequestOrNotFound,
487 | withReducer('state', 'dispatch', reducer, new State())
488 | )(TalentRequestsDetailPage);
489 |
--------------------------------------------------------------------------------
/packages/recon-engine/src/parse/parseModule.js:
--------------------------------------------------------------------------------
1 | const Babylon = require('babylon');
2 | //import pullSymbols from './pullSymbols';
3 | const T = require('babel-types');
4 | const traverse = require('babel-traverse').default;
5 | const isReactComponent = require('../utils/isReactComponent');
6 |
7 | /** Provide the ast from module source */
8 | function parseSource(moduleSource) {
9 | return Babylon.parse(moduleSource, {
10 | sourceType: 'module',
11 | plugins: [
12 | 'jsx',
13 | 'flow',
14 | 'objectRestSpread',
15 | 'asyncFunctions',
16 | 'classConstructorCall',
17 | 'doExpressions',
18 | 'trailingFunctionCommas',
19 | 'decorators',
20 | 'classProperties',
21 | 'exportExtensions',
22 | 'exponentiationOperator',
23 | 'asyncGenerators',
24 | 'functionBind',
25 | 'functionSent',
26 | 'dynamicImport',
27 | // keep up-to-date
28 | ],
29 | });
30 | }
31 |
32 | /** Provide an internal Recon type definition */
33 | function resolveType(node, data = {}) {
34 | return Object.assign({type: node.type, __node: node}, data);
35 | }
36 |
37 | /** Pull TOP LEVEL symbols out of our ast */
38 | function pullSymbols(ast) {
39 | const symbols = [];
40 |
41 | // TODO: Need to think hard about how we store each symbol "type" to allow easy resolution later
42 |
43 | function pushVariableDeclarator(node) {
44 | symbols.push({
45 | name: node.id.name,
46 | type: resolveType(node.init),
47 | });
48 | }
49 |
50 | function pushVariableDeclaration(node) {
51 | node.declarations.forEach(declNode => pushVariableDeclarator(declNode));
52 | }
53 |
54 | function pushFunctionDeclaration(node) {
55 | symbols.push({
56 | name: node.id.name,
57 | type: resolveType(node),
58 | });
59 | }
60 |
61 | function pushClassDeclaration(node) {
62 | symbols.push({
63 | name: node.id.name,
64 | type: resolveType(node),
65 | });
66 | }
67 |
68 | function pushExportSpecifier(node, {source, sourceName} = {}) {
69 | symbols.push({
70 | name: `export::${node.exported.name}`,
71 | type: resolveType(node, {source, sourceName}),
72 | });
73 | }
74 |
75 | function pushExportDeclaration(node) {
76 | // We'll collect two symbols for export declarations. One is
77 | // the declared value/type and the other will simply be a pointer
78 | // with name `export::symbolName`
79 | if (T.isFunctionDeclaration(node)) {
80 | pushFunctionDeclaration(node);
81 | symbols.push({
82 | name: `export::${node.id.name}`,
83 | type: resolveType(node.id),
84 | });
85 | } else if (T.isVariableDeclaration(node)) {
86 | pushVariableDeclaration(node);
87 | node.declarations.forEach(declNode =>
88 | symbols.push({
89 | name: `export::${declNode.id.name}`,
90 | type: resolveType(declNode.id),
91 | }));
92 | } else if (T.isClassDeclaration(node)) {
93 | pushClassDeclaration(node);
94 | symbols.push({
95 | name: `export::${node.id.name}`,
96 | type: resolveType(node.id),
97 | });
98 | }
99 | }
100 |
101 | function pushExportNamedDeclaration(node) {
102 | if (node.declaration) {
103 | pushExportDeclaration(node.declaration);
104 | } else {
105 | const source = node.source ? node.source.value : undefined;
106 | node.specifiers.forEach(spec =>
107 | pushExportSpecifier(spec, {source, sourceName: spec.local.name}));
108 | }
109 | }
110 |
111 | function pushExportDefaultDeclaration(node) {
112 | const decl = node.declaration;
113 |
114 | if (T.isFunctionDeclaration(decl)) {
115 | pushFunctionDeclaration(decl);
116 | symbols.push({
117 | name: `export::default`,
118 | type: resolveType(decl.id),
119 | });
120 | } else if (T.isVariableDeclaration(decl)) {
121 | pushVariableDeclaration(decl);
122 | decl.declarations.forEach(vDecl =>
123 | symbols.push({
124 | name: `export::default`,
125 | type: resolveType(vDecl.id),
126 | }));
127 | } else if (T.isClassDeclaration(decl)) {
128 | pushClassDeclaration(decl);
129 | symbols.push({
130 | name: `export::default`,
131 | type: resolveType(decl.id),
132 | });
133 | } else {
134 | symbols.push({
135 | name: `export::default`,
136 | type: resolveType(decl),
137 | });
138 | }
139 | }
140 |
141 | function pushImportDeclaration(node) {
142 | const source = node.source.value;
143 | node.specifiers.forEach(spec =>
144 | symbols.push({
145 | name: T.isIdentifier(spec.exported)
146 | ? spec.exported.value
147 | : spec.local.name,
148 | type: resolveType(spec, {source, sourceName: spec.local.name}),
149 | }));
150 | }
151 |
152 | const visitor = {
153 | FunctionDeclaration(path) {
154 | if (T.isProgram(path.parent)) {
155 | pushFunctionDeclaration(path.node);
156 | }
157 | path.skip();
158 | },
159 | VariableDeclaration(path) {
160 | if (T.isProgram(path.parent)) {
161 | pushVariableDeclaration(path.node);
162 | }
163 | path.skip();
164 | },
165 | ClassDeclaration(path) {
166 | if (T.isProgram(path.parent)) {
167 | pushClassDeclaration(path.node);
168 | }
169 | path.skip();
170 | },
171 | ExportNamedDeclaration(path) {
172 | pushExportNamedDeclaration(path.node);
173 | path.skip();
174 | },
175 | ExportDefaultDeclaration(path) {
176 | pushExportDefaultDeclaration(path.node);
177 | path.skip();
178 | },
179 | ImportDeclaration(path) {
180 | pushImportDeclaration(path.node);
181 | path.skip();
182 | },
183 | };
184 |
185 | traverse(ast, visitor);
186 | return [...symbols];
187 | }
188 |
189 | /** Pull dep & usage info out of a render method/func ast */
190 | function pullDeps(ast) {
191 | const deps = [];
192 |
193 | // TODO: Search React.createElement
194 | // TODO: Allow other syntaxes such as hyperscript? part of plugin/config customisation
195 | // TODO: Might be useful to track depth and hierarchy? At least *definitely* useful to track children for each usage
196 |
197 | const visitor = {
198 | JSXElement(path) {
199 | const name = path.node.openingElement.name.name;
200 |
201 | deps.push({
202 | name,
203 | selfClosing: path.node.openingElement.selfClosing,
204 | props: path.node.openingElement.attributes.map(
205 | attr =>
206 | T.isJSXSpreadAttribute(attr)
207 | ? {
208 | name: '__spread',
209 | type: resolveType(attr.argument),
210 | }
211 | : {
212 | name: attr.name.name,
213 | // TODO: see if we can find union of possible values. Eg. color = someVar ? 'green' : 'red'
214 | // TODO: for simple identifier types we could sometimes resolve to component prop types
215 | type: T.isJSXExpressionContainer(attr.value)
216 | ? resolveType(attr.value.expression)
217 | : resolveType(attr.value),
218 | }
219 | ),
220 | });
221 | },
222 |
223 | noScope: true,
224 | };
225 |
226 | traverse(ast, visitor);
227 | return [...deps];
228 | }
229 |
230 | /** Search declarations and references to see if prop types are defined (FLOW?) */
231 | function findProps(/* path */) {
232 | const props = [];
233 |
234 | // TODO: Pull static def from classes ie. static propTypes = {}
235 | // TODO: Look for mutations ie. MyComponent.propTypes = {};
236 | // TODO: Look at *actually referenced* props in render/class methods
237 | // TODO: Look for rest/spread props (and what component they're inherited from)
238 | // TODO: Pull out values where possible. Eg easy StringLiteral and NumericLiteral
239 | // TODO: With above we can structure data to be literal or a list of possible values - ie. maybe we can pull from propTypes, ...
240 | // resolve basic ternaries or even pull from basic hash maps & lists (maybe first-class immutable support? :D)
241 |
242 | return [...props];
243 | }
244 |
245 | /**
246 | * Should we pull this component path?
247 | * Currently: is it considered "top level"? Ie. not in closures/constructors etc.
248 | */
249 | function shouldPullComponent(path) {
250 | let tPath = path.parentPath;
251 | while (tPath) {
252 | if (T.isProgram(tPath)) {
253 | return true;
254 | }
255 |
256 | if (
257 | !T.isExportDefaultDeclaration(tPath) &&
258 | !T.isExportNamedDeclaration(tPath) &&
259 | !T.isVariableDeclaration(tPath)
260 | ) {
261 | break;
262 | }
263 |
264 | tPath = tPath.parentPath;
265 | }
266 |
267 | return false;
268 | }
269 |
270 | /** Get render method */
271 | function getRenderMethod(node) {
272 | if (T.isArrowFunctionExpression(node) || T.isFunctionExpression(node)) {
273 | return node;
274 | }
275 |
276 | if (T.isFunctionDeclaration(node)) {
277 | return node;
278 | }
279 |
280 | if (T.isClassDeclaration(node)) {
281 | return node.body.body.find(
282 | bNode => T.isClassMethod(bNode) && bNode.key.name === 'render'
283 | );
284 | }
285 |
286 | throw new Error('Unsupported component definition :S');
287 | }
288 |
289 | /** Search for static components in our module */
290 | function pullStaticComponents(ast, {globalId, definedIn}) {
291 | const components = [];
292 |
293 | // TODO: Look at top level CallExpression's and if we can resolve the function decl and it returns a component we can save that!!!
294 |
295 | function visitReactComponent(path) {
296 | if (isReactComponent(path.node)) {
297 | const renderMethod = getRenderMethod(path.node);
298 |
299 | if (T.isArrowFunctionExpression(path) || T.isFunctionExpression(path)) {
300 | // for expressions we need to find the parent variable
301 | // declarator in order to name it. As we traverse we can
302 | // also gather "enhancements"
303 | // TODO: Gather enhancements off of decorators
304 | let tPath = path.parentPath;
305 | let name = null;
306 | const enhancements = [];
307 | while (tPath) {
308 | // yay! we found the variable
309 | if (T.isVariableDeclarator(tPath)) {
310 | if (!shouldPullComponent(tPath)) {
311 | return;
312 | }
313 | name = tPath.node.id.name;
314 | break;
315 | }
316 |
317 | // gather "enhancements"
318 | if (T.isCallExpression(tPath)) {
319 | enhancements.push(tPath.node);
320 | }
321 |
322 | tPath = tPath.parentPath;
323 | }
324 |
325 | components.push({
326 | id: globalId(name),
327 | name,
328 | type: resolveType(path.node),
329 | enhancements: [...enhancements],
330 | props: findProps(path),
331 | deps: pullDeps(renderMethod),
332 | definedIn,
333 | });
334 | }
335 |
336 | if (T.isFunctionDeclaration(path) && shouldPullComponent(path)) {
337 | components.push({
338 | id: globalId(path.node.id.name),
339 | name: path.node.id.name,
340 | type: resolveType(path.node),
341 | enhancements: [],
342 | props: findProps(path),
343 | deps: pullDeps(renderMethod),
344 | definedIn,
345 | });
346 | }
347 |
348 | if (T.isClassDeclaration(path) && shouldPullComponent(path)) {
349 | components.push({
350 | id: globalId(path.node.id.name),
351 | name: path.node.id.name,
352 | type: resolveType(path.node),
353 | enhancements: [],
354 | props: findProps(path),
355 | deps: pullDeps(renderMethod),
356 | definedIn,
357 | });
358 | }
359 |
360 | // TODO: Pull more meta data... eg. attached docblocs etc
361 | }
362 |
363 | path.skip();
364 | }
365 |
366 | const visitor = {
367 | ArrowFunctionExpression: visitReactComponent,
368 | FunctionDeclaration: visitReactComponent,
369 | FunctionExpression: visitReactComponent,
370 | ClassDeclaration: visitReactComponent,
371 | };
372 |
373 | traverse(ast, visitor);
374 | return [...components];
375 | }
376 |
377 | /** Pull first found return value of a function ast */
378 | function getReturnValue(ast) {
379 | let value;
380 |
381 | const visitor = {
382 | ReturnStatement(path) {
383 | value = path.node.argument;
384 | path.stop();
385 | },
386 |
387 | noScope: true,
388 | };
389 |
390 | traverse(ast, visitor);
391 | return value;
392 | }
393 |
394 | /** Search for dynamically created components within our ast */
395 | function pullDynamicComponents(symbols, {globalId, definedIn}) {
396 | return symbols
397 | .map(sym => {
398 | const call = sym.type.__node;
399 | if (!T.isCallExpression(call)) {
400 | return null;
401 | }
402 |
403 | // only handle function calls atm, looking into obj/methods later...
404 | if (!T.isIdentifier(call.callee)) {
405 | return null;
406 | }
407 |
408 | // search for local symbol which is a function. This is all (local) we'll
409 | // support for now. Perhaps this will need to move to resolve later.
410 | const creator = symbols.find(s => s.name === call.callee.name);
411 | if (
412 | !creator ||
413 | (!T.isFunctionDeclaration(creator.type.__node) &&
414 | !T.isFunctionExpression(creator.type.__node))
415 | ) {
416 | return null;
417 | }
418 |
419 | // TODO: Maybe support multiple definitions?
420 | const returnValue = getReturnValue(creator.type.__node.body);
421 | if (!returnValue || !isReactComponent(returnValue)) {
422 | return null;
423 | }
424 |
425 | const renderMethod = getRenderMethod(returnValue);
426 | return {
427 | id: globalId(sym.name),
428 | name: sym.name,
429 | type: resolveType(returnValue),
430 | enhancements: [],
431 | props: [], // TODO: findProps(path),
432 | deps: pullDeps(renderMethod),
433 | createdBy: creator,
434 | definedIn,
435 | };
436 | })
437 | .filter(c => !!c);
438 | }
439 |
440 | /** Pull all Identifier nodes within an ast */
441 | function getIdentifiers(ast) {
442 | const identifiers = [];
443 |
444 | const visitor = {
445 | Identifier(path) {
446 | identifiers.push(path.node);
447 | },
448 |
449 | noScope: true,
450 | };
451 |
452 | traverse(ast, visitor);
453 | return [...identifiers];
454 | }
455 |
456 | /** Pull all CallExpression nodes within an ast */
457 | function getCallExpressions(ast) {
458 | const callExpressions = [];
459 |
460 | const visitor = {
461 | CallExpression(path) {
462 | callExpressions.push(path.node);
463 | },
464 |
465 | noScope: true,
466 | };
467 |
468 | traverse(ast, visitor);
469 | return [...callExpressions];
470 | }
471 |
472 | /**
473 | * Search symbols for anything that is a potential path to components
474 | * Ie. Could simply be reference to or an enhancement path
475 | */
476 | function getPotentialComponentPaths(symbols, components) {
477 | return symbols
478 | .map(sym => {
479 | return T.isCallExpression(sym.type.__node)
480 | ? {
481 | name: sym.name,
482 | enhancements: [
483 | sym.type.__node,
484 | ...getCallExpressions(sym.type.__node),
485 | ],
486 | // TODO: What if we had another intermediate enhancement path? we wouldn't find the component definition
487 | targets: getIdentifiers(sym.type.__node)
488 | .filter(i => components.find(c => c.name === i.name))
489 | .map(i => ({name: i.name, type: resolveType(i)})),
490 | }
491 | : {targets: []};
492 | })
493 | .filter(a => !!a.targets.length);
494 | }
495 |
496 | /** Pull structured data from an ast */
497 | function pullData(ast, opts) {
498 | const symbols = pullSymbols(ast, opts);
499 | const staticComponents = pullStaticComponents(ast, opts);
500 | const dynamicComponents = pullDynamicComponents(symbols, opts);
501 | const components = staticComponents.concat(dynamicComponents);
502 | const potentialComponentPaths = getPotentialComponentPaths(
503 | symbols,
504 | components,
505 | opts
506 | );
507 |
508 | return {
509 | symbols,
510 | components,
511 | potentialComponentPaths,
512 | };
513 | }
514 |
515 | /** Given a source module extract and provide a parsed module */
516 | function parseModule({path, src, id}) {
517 | function globalId(symbolName) {
518 | return `${id}::${symbolName}`;
519 | }
520 |
521 | try {
522 | const ast = parseSource(src);
523 | const data = pullData(ast, {globalId, definedIn: path});
524 |
525 | return {
526 | path,
527 | data,
528 | };
529 | } catch (error) {
530 | return {
531 | error,
532 | path,
533 | data: {
534 | symbols: [],
535 | components: [],
536 | potentialComponentPaths: [],
537 | },
538 | };
539 | }
540 | }
541 |
542 | module.exports = parseModule;
543 |
--------------------------------------------------------------------------------
/flow/babel.js.flow:
--------------------------------------------------------------------------------
1 | // Below is taken from https://github.com/babel/babel/tree/master/lib
2 | // Hopefully will be packaged up soon?
3 |
4 | declare type BabelFileModulesMetadata = {
5 | imports: Array,
6 | exports: {
7 | exported: Array,
8 | specifiers: Array
9 | }
10 | };
11 |
12 | declare type BabelFileMetadata = {
13 | usedHelpers: Array;
14 |
15 | marked: Array<{
16 | type: string;
17 | message: string;
18 | loc: Object;
19 | }>;
20 |
21 | modules: BabelFileModulesMetadata
22 | };
23 |
24 | declare type BabelFileResult = {
25 | ast?: ?Object;
26 | code?: ?string;
27 | map?: ?Object;
28 | ignored?: ?boolean;
29 | metadata?: ?BabelFileMetadata;
30 | };
31 |
32 | declare type BabelParserOptions = {
33 | strictMode?: boolean;
34 | looseModules?: boolean;
35 | highlightCode?: boolean;
36 | nonStandard?: boolean;
37 | sourceType?: "module" | "script";
38 | filename?: string;
39 | features?: Object;
40 | plugins?: Object;
41 | };
42 |
43 | // NOTE: This file is autogenerated. Do not modify.
44 | // See scripts/generate-interfaces.js for script used.
45 |
46 | declare class BabelNodeComment {
47 | value: string;
48 | start: number;
49 | end: number;
50 | loc: BabelNodeSourceLocation;
51 | }
52 |
53 | declare class BabelNodeBlockComment extends BabelNodeComment {
54 | type: "BlockComment";
55 | }
56 |
57 | declare class BabelNodeLineComment extends BabelNodeComment {
58 | type: "LineComment";
59 | }
60 |
61 | declare class BabelNodeSourceLocation {
62 | start: {
63 | line: number;
64 | column: number;
65 | };
66 |
67 | end: {
68 | line: number;
69 | column: number;
70 | };
71 | }
72 |
73 | declare class BabelNode {
74 | leadingComments: ?Array;
75 | innerComments: ?Array;
76 | trailingComments: ?Array;
77 | start: ?number;
78 | end: ?number;
79 | loc: ?BabelNodeSourceLocation;
80 | }
81 |
82 | declare class BabelNodeArrayExpression extends BabelNode {
83 | type: "ArrayExpression";
84 | elements?: any;
85 | }
86 |
87 | declare class BabelNodeAssignmentExpression extends BabelNode {
88 | type: "AssignmentExpression";
89 | operator: string;
90 | left: BabelNodeLVal;
91 | right: BabelNodeExpression;
92 | }
93 |
94 | declare class BabelNodeBinaryExpression extends BabelNode {
95 | type: "BinaryExpression";
96 | operator: "+" | "-" | "/" | "%" | "*" | "**" | "&" | "|" | ">>" | ">>>" | "<<" | "^" | "==" | "===" | "!=" | "!==" | "in" | "instanceof" | ">" | "<" | ">=" | "<=";
97 | left: BabelNodeExpression;
98 | right: BabelNodeExpression;
99 | }
100 |
101 | declare class BabelNodeDirective extends BabelNode {
102 | type: "Directive";
103 | value: BabelNodeDirectiveLiteral;
104 | }
105 |
106 | declare class BabelNodeDirectiveLiteral extends BabelNode {
107 | type: "DirectiveLiteral";
108 | value: string;
109 | }
110 |
111 | declare class BabelNodeBlockStatement extends BabelNode {
112 | type: "BlockStatement";
113 | directives?: any;
114 | body: any;
115 | }
116 |
117 | declare class BabelNodeBreakStatement extends BabelNode {
118 | type: "BreakStatement";
119 | label?: ?BabelNodeIdentifier;
120 | }
121 |
122 | declare class BabelNodeCallExpression extends BabelNode {
123 | type: "CallExpression";
124 | callee: BabelNodeExpression;
125 | arguments: any;
126 | }
127 |
128 | declare class BabelNodeCatchClause extends BabelNode {
129 | type: "CatchClause";
130 | param: BabelNodeIdentifier;
131 | body: BabelNodeBlockStatement;
132 | }
133 |
134 | declare class BabelNodeConditionalExpression extends BabelNode {
135 | type: "ConditionalExpression";
136 | test: BabelNodeExpression;
137 | consequent: BabelNodeExpression;
138 | alternate: BabelNodeExpression;
139 | }
140 |
141 | declare class BabelNodeContinueStatement extends BabelNode {
142 | type: "ContinueStatement";
143 | label?: ?BabelNodeIdentifier;
144 | }
145 |
146 | declare class BabelNodeDebuggerStatement extends BabelNode {
147 | type: "DebuggerStatement";
148 | }
149 |
150 | declare class BabelNodeDoWhileStatement extends BabelNode {
151 | type: "DoWhileStatement";
152 | test: BabelNodeExpression;
153 | body: BabelNodeStatement;
154 | }
155 |
156 | declare class BabelNodeEmptyStatement extends BabelNode {
157 | type: "EmptyStatement";
158 | }
159 |
160 | declare class BabelNodeExpressionStatement extends BabelNode {
161 | type: "ExpressionStatement";
162 | expression: BabelNodeExpression;
163 | }
164 |
165 | declare class BabelNodeFile extends BabelNode {
166 | type: "File";
167 | program: BabelNodeProgram;
168 | comments: any;
169 | tokens: any;
170 | }
171 |
172 | declare class BabelNodeForInStatement extends BabelNode {
173 | type: "ForInStatement";
174 | left: BabelNodeVariableDeclaration | BabelNodeLVal;
175 | right: BabelNodeExpression;
176 | body: BabelNodeStatement;
177 | }
178 |
179 | declare class BabelNodeForStatement extends BabelNode {
180 | type: "ForStatement";
181 | init?: ?BabelNodeVariableDeclaration | BabelNodeExpression;
182 | test?: ?BabelNodeExpression;
183 | update?: ?BabelNodeExpression;
184 | body: BabelNodeStatement;
185 | }
186 |
187 | declare class BabelNodeFunctionDeclaration extends BabelNode {
188 | type: "FunctionDeclaration";
189 | id: BabelNodeIdentifier;
190 | params: any;
191 | body: BabelNodeBlockStatement;
192 | generator?: boolean;
193 | async?: boolean;
194 | returnType: any;
195 | typeParameters: any;
196 | }
197 |
198 | declare class BabelNodeFunctionExpression extends BabelNode {
199 | type: "FunctionExpression";
200 | id?: ?BabelNodeIdentifier;
201 | params: any;
202 | body: BabelNodeBlockStatement;
203 | generator?: boolean;
204 | async?: boolean;
205 | returnType: any;
206 | typeParameters: any;
207 | }
208 |
209 | declare class BabelNodeIdentifier extends BabelNode {
210 | type: "Identifier";
211 | name: any;
212 | typeAnnotation: any;
213 | }
214 |
215 | declare class BabelNodeIfStatement extends BabelNode {
216 | type: "IfStatement";
217 | test: BabelNodeExpression;
218 | consequent: BabelNodeStatement;
219 | alternate?: ?BabelNodeStatement;
220 | }
221 |
222 | declare class BabelNodeLabeledStatement extends BabelNode {
223 | type: "LabeledStatement";
224 | label: BabelNodeIdentifier;
225 | body: BabelNodeStatement;
226 | }
227 |
228 | declare class BabelNodeStringLiteral extends BabelNode {
229 | type: "StringLiteral";
230 | value: string;
231 | }
232 |
233 | declare class BabelNodeNumericLiteral extends BabelNode {
234 | type: "NumericLiteral";
235 | value: number;
236 | }
237 |
238 | declare class BabelNodeNullLiteral extends BabelNode {
239 | type: "NullLiteral";
240 | }
241 |
242 | declare class BabelNodeBooleanLiteral extends BabelNode {
243 | type: "BooleanLiteral";
244 | value: boolean;
245 | }
246 |
247 | declare class BabelNodeRegExpLiteral extends BabelNode {
248 | type: "RegExpLiteral";
249 | pattern: string;
250 | flags?: string;
251 | }
252 |
253 | declare class BabelNodeLogicalExpression extends BabelNode {
254 | type: "LogicalExpression";
255 | operator: "||" | "&&";
256 | left: BabelNodeExpression;
257 | right: BabelNodeExpression;
258 | }
259 |
260 | declare class BabelNodeMemberExpression extends BabelNode {
261 | type: "MemberExpression";
262 | object: BabelNodeExpression;
263 | property: any;
264 | computed?: boolean;
265 | }
266 |
267 | declare class BabelNodeNewExpression extends BabelNode {
268 | type: "NewExpression";
269 | callee: BabelNodeExpression;
270 | arguments: any;
271 | }
272 |
273 | declare class BabelNodeProgram extends BabelNode {
274 | type: "Program";
275 | directives?: any;
276 | body: any;
277 | }
278 |
279 | declare class BabelNodeObjectExpression extends BabelNode {
280 | type: "ObjectExpression";
281 | properties: any;
282 | }
283 |
284 | declare class BabelNodeObjectMethod extends BabelNode {
285 | type: "ObjectMethod";
286 | kind?: any;
287 | computed?: boolean;
288 | key: any;
289 | decorators: any;
290 | body: BabelNodeBlockStatement;
291 | generator?: boolean;
292 | async?: boolean;
293 | params: any;
294 | returnType: any;
295 | typeParameters: any;
296 | }
297 |
298 | declare class BabelNodeObjectProperty extends BabelNode {
299 | type: "ObjectProperty";
300 | computed?: boolean;
301 | key: any;
302 | value: BabelNodeExpression;
303 | shorthand?: boolean;
304 | decorators?: any;
305 | }
306 |
307 | declare class BabelNodeRestElement extends BabelNode {
308 | type: "RestElement";
309 | argument: BabelNodeLVal;
310 | typeAnnotation: any;
311 | }
312 |
313 | declare class BabelNodeReturnStatement extends BabelNode {
314 | type: "ReturnStatement";
315 | argument?: ?BabelNodeExpression;
316 | }
317 |
318 | declare class BabelNodeSequenceExpression extends BabelNode {
319 | type: "SequenceExpression";
320 | expressions: any;
321 | }
322 |
323 | declare class BabelNodeSwitchCase extends BabelNode {
324 | type: "SwitchCase";
325 | test?: ?BabelNodeExpression;
326 | consequent: any;
327 | }
328 |
329 | declare class BabelNodeSwitchStatement extends BabelNode {
330 | type: "SwitchStatement";
331 | discriminant: BabelNodeExpression;
332 | cases: any;
333 | }
334 |
335 | declare class BabelNodeThisExpression extends BabelNode {
336 | type: "ThisExpression";
337 | }
338 |
339 | declare class BabelNodeThrowStatement extends BabelNode {
340 | type: "ThrowStatement";
341 | argument: BabelNodeExpression;
342 | }
343 |
344 | declare class BabelNodeTryStatement extends BabelNode {
345 | type: "TryStatement";
346 | body: BabelNodeBlockStatement;
347 | handler?: any;
348 | finalizer?: ?BabelNodeBlockStatement;
349 | block: any;
350 | }
351 |
352 | declare class BabelNodeUnaryExpression extends BabelNode {
353 | type: "UnaryExpression";
354 | prefix?: boolean;
355 | argument: BabelNodeExpression;
356 | operator: "void" | "delete" | "!" | "+" | "-" | "++" | "--" | "~" | "typeof";
357 | }
358 |
359 | declare class BabelNodeUpdateExpression extends BabelNode {
360 | type: "UpdateExpression";
361 | prefix?: boolean;
362 | argument: BabelNodeExpression;
363 | operator: "++" | "--";
364 | }
365 |
366 | declare class BabelNodeVariableDeclaration extends BabelNode {
367 | type: "VariableDeclaration";
368 | kind: any;
369 | declarations: any;
370 | }
371 |
372 | declare class BabelNodeVariableDeclarator extends BabelNode {
373 | type: "VariableDeclarator";
374 | id: BabelNodeLVal;
375 | init?: ?BabelNodeExpression;
376 | }
377 |
378 | declare class BabelNodeWhileStatement extends BabelNode {
379 | type: "WhileStatement";
380 | test: BabelNodeExpression;
381 | body: BabelNodeBlockStatement | BabelNodeStatement;
382 | }
383 |
384 | declare class BabelNodeWithStatement extends BabelNode {
385 | type: "WithStatement";
386 | object: any;
387 | body: BabelNodeBlockStatement | BabelNodeStatement;
388 | }
389 |
390 | declare class BabelNodeAssignmentPattern extends BabelNode {
391 | type: "AssignmentPattern";
392 | left: BabelNodeIdentifier;
393 | right: BabelNodeExpression;
394 | }
395 |
396 | declare class BabelNodeArrayPattern extends BabelNode {
397 | type: "ArrayPattern";
398 | elements: any;
399 | typeAnnotation: any;
400 | }
401 |
402 | declare class BabelNodeArrowFunctionExpression extends BabelNode {
403 | type: "ArrowFunctionExpression";
404 | params: any;
405 | body: BabelNodeBlockStatement | BabelNodeExpression;
406 | async?: boolean;
407 | returnType: any;
408 | }
409 |
410 | declare class BabelNodeClassBody extends BabelNode {
411 | type: "ClassBody";
412 | body: any;
413 | }
414 |
415 | declare class BabelNodeClassDeclaration extends BabelNode {
416 | type: "ClassDeclaration";
417 | id: BabelNodeIdentifier;
418 | body: BabelNodeClassBody;
419 | superClass?: ?BabelNodeExpression;
420 | decorators: any;
421 | mixins: any;
422 | typeParameters: any;
423 | superTypeParameters: any;
424 | }
425 |
426 | declare class BabelNodeClassExpression extends BabelNode {
427 | type: "ClassExpression";
428 | id?: ?BabelNodeIdentifier;
429 | body: BabelNodeClassBody;
430 | superClass?: ?BabelNodeExpression;
431 | decorators: any;
432 | mixins: any;
433 | typeParameters: any;
434 | superTypeParameters: any;
435 | }
436 |
437 | declare class BabelNodeExportAllDeclaration extends BabelNode {
438 | type: "ExportAllDeclaration";
439 | source: BabelNodeStringLiteral;
440 | }
441 |
442 | declare class BabelNodeExportDefaultDeclaration extends BabelNode {
443 | type: "ExportDefaultDeclaration";
444 | declaration: BabelNodeFunctionDeclaration | BabelNodeClassDeclaration | BabelNodeExpression;
445 | }
446 |
447 | declare class BabelNodeExportNamedDeclaration extends BabelNode {
448 | type: "ExportNamedDeclaration";
449 | declaration?: ?BabelNodeDeclaration;
450 | specifiers: any;
451 | source?: ?BabelNodeStringLiteral;
452 | }
453 |
454 | declare class BabelNodeExportSpecifier extends BabelNode {
455 | type: "ExportSpecifier";
456 | local: BabelNodeIdentifier;
457 | imported: BabelNodeIdentifier;
458 | exported: any;
459 | }
460 |
461 | declare class BabelNodeForOfStatement extends BabelNode {
462 | type: "ForOfStatement";
463 | left: BabelNodeVariableDeclaration | BabelNodeLVal;
464 | right: BabelNodeExpression;
465 | body: BabelNodeStatement;
466 | }
467 |
468 | declare class BabelNodeImportDeclaration extends BabelNode {
469 | type: "ImportDeclaration";
470 | specifiers: any;
471 | source: BabelNodeStringLiteral;
472 | }
473 |
474 | declare class BabelNodeImportDefaultSpecifier extends BabelNode {
475 | type: "ImportDefaultSpecifier";
476 | local: BabelNodeIdentifier;
477 | }
478 |
479 | declare class BabelNodeImportNamespaceSpecifier extends BabelNode {
480 | type: "ImportNamespaceSpecifier";
481 | local: BabelNodeIdentifier;
482 | }
483 |
484 | declare class BabelNodeImportSpecifier extends BabelNode {
485 | type: "ImportSpecifier";
486 | local: BabelNodeIdentifier;
487 | imported: BabelNodeIdentifier;
488 | }
489 |
490 | declare class BabelNodeMetaProperty extends BabelNode {
491 | type: "MetaProperty";
492 | meta: string;
493 | property: string;
494 | }
495 |
496 | declare class BabelNodeClassMethod extends BabelNode {
497 | type: "ClassMethod";
498 | kind?: any;
499 | computed?: boolean;
500 | key: any;
501 | params: any;
502 | body: BabelNodeBlockStatement;
503 | generator?: boolean;
504 | async?: boolean;
505 | decorators: any;
506 | returnType: any;
507 | typeParameters: any;
508 | }
509 |
510 | declare class BabelNodeObjectPattern extends BabelNode {
511 | type: "ObjectPattern";
512 | properties: any;
513 | typeAnnotation: any;
514 | }
515 |
516 | declare class BabelNodeSpreadElement extends BabelNode {
517 | type: "SpreadElement";
518 | argument: BabelNodeExpression;
519 | }
520 |
521 | declare class BabelNodeSuper extends BabelNode {
522 | type: "Super";
523 | }
524 |
525 | declare class BabelNodeTaggedTemplateExpression extends BabelNode {
526 | type: "TaggedTemplateExpression";
527 | tag: BabelNodeExpression;
528 | quasi: BabelNodeTemplateLiteral;
529 | }
530 |
531 | declare class BabelNodeTemplateElement extends BabelNode {
532 | type: "TemplateElement";
533 | value: any;
534 | tail?: boolean;
535 | }
536 |
537 | declare class BabelNodeTemplateLiteral extends BabelNode {
538 | type: "TemplateLiteral";
539 | quasis: any;
540 | expressions: any;
541 | }
542 |
543 | declare class BabelNodeYieldExpression extends BabelNode {
544 | type: "YieldExpression";
545 | delegate?: boolean;
546 | argument?: ?BabelNodeExpression;
547 | }
548 |
549 | declare class BabelNodeAnyTypeAnnotation extends BabelNode {
550 | type: "AnyTypeAnnotation";
551 | }
552 |
553 | declare class BabelNodeArrayTypeAnnotation extends BabelNode {
554 | type: "ArrayTypeAnnotation";
555 | elementType: any;
556 | }
557 |
558 | declare class BabelNodeBooleanTypeAnnotation extends BabelNode {
559 | type: "BooleanTypeAnnotation";
560 | }
561 |
562 | declare class BabelNodeBooleanLiteralTypeAnnotation extends BabelNode {
563 | type: "BooleanLiteralTypeAnnotation";
564 | }
565 |
566 | declare class BabelNodeNullLiteralTypeAnnotation extends BabelNode {
567 | type: "NullLiteralTypeAnnotation";
568 | }
569 |
570 | declare class BabelNodeClassImplements extends BabelNode {
571 | type: "ClassImplements";
572 | id: any;
573 | typeParameters: any;
574 | }
575 |
576 | declare class BabelNodeClassProperty extends BabelNode {
577 | type: "ClassProperty";
578 | key: any;
579 | value: any;
580 | typeAnnotation: any;
581 | decorators: any;
582 | }
583 |
584 | declare class BabelNodeDeclareClass extends BabelNode {
585 | type: "DeclareClass";
586 | id: any;
587 | typeParameters: any;
588 | body: any;
589 | }
590 |
591 | declare class BabelNodeDeclareFunction extends BabelNode {
592 | type: "DeclareFunction";
593 | id: any;
594 | }
595 |
596 | declare class BabelNodeDeclareInterface extends BabelNode {
597 | type: "DeclareInterface";
598 | id: any;
599 | typeParameters: any;
600 | body: any;
601 | }
602 |
603 | declare class BabelNodeDeclareModule extends BabelNode {
604 | type: "DeclareModule";
605 | id: any;
606 | body: any;
607 | }
608 |
609 | declare class BabelNodeDeclareTypeAlias extends BabelNode {
610 | type: "DeclareTypeAlias";
611 | id: any;
612 | typeParameters: any;
613 | right: any;
614 | }
615 |
616 | declare class BabelNodeDeclareVariable extends BabelNode {
617 | type: "DeclareVariable";
618 | id: any;
619 | }
620 |
621 | declare class BabelNodeExistentialTypeParam extends BabelNode {
622 | type: "ExistentialTypeParam";
623 | }
624 |
625 | declare class BabelNodeFunctionTypeAnnotation extends BabelNode {
626 | type: "FunctionTypeAnnotation";
627 | typeParameters: any;
628 | params: any;
629 | rest: any;
630 | returnType: any;
631 | }
632 |
633 | declare class BabelNodeFunctionTypeParam extends BabelNode {
634 | type: "FunctionTypeParam";
635 | name: any;
636 | typeAnnotation: any;
637 | }
638 |
639 | declare class BabelNodeGenericTypeAnnotation extends BabelNode {
640 | type: "GenericTypeAnnotation";
641 | id: any;
642 | typeParameters: any;
643 | }
644 |
645 | declare class BabelNodeInterfaceExtends extends BabelNode {
646 | type: "InterfaceExtends";
647 | id: any;
648 | typeParameters: any;
649 | }
650 |
651 | declare class BabelNodeInterfaceDeclaration extends BabelNode {
652 | type: "InterfaceDeclaration";
653 | id: any;
654 | typeParameters: any;
655 | body: any;
656 | }
657 |
658 | declare class BabelNodeIntersectionTypeAnnotation extends BabelNode {
659 | type: "IntersectionTypeAnnotation";
660 | types: any;
661 | }
662 |
663 | declare class BabelNodeMixedTypeAnnotation extends BabelNode {
664 | type: "MixedTypeAnnotation";
665 | }
666 |
667 | declare class BabelNodeNullableTypeAnnotation extends BabelNode {
668 | type: "NullableTypeAnnotation";
669 | typeAnnotation: any;
670 | }
671 |
672 | declare class BabelNodeNumericLiteralTypeAnnotation extends BabelNode {
673 | type: "NumericLiteralTypeAnnotation";
674 | }
675 |
676 | declare class BabelNodeNumberTypeAnnotation extends BabelNode {
677 | type: "NumberTypeAnnotation";
678 | }
679 |
680 | declare class BabelNodeStringLiteralTypeAnnotation extends BabelNode {
681 | type: "StringLiteralTypeAnnotation";
682 | }
683 |
684 | declare class BabelNodeStringTypeAnnotation extends BabelNode {
685 | type: "StringTypeAnnotation";
686 | }
687 |
688 | declare class BabelNodeThisTypeAnnotation extends BabelNode {
689 | type: "ThisTypeAnnotation";
690 | }
691 |
692 | declare class BabelNodeTupleTypeAnnotation extends BabelNode {
693 | type: "TupleTypeAnnotation";
694 | types: any;
695 | }
696 |
697 | declare class BabelNodeTypeofTypeAnnotation extends BabelNode {
698 | type: "TypeofTypeAnnotation";
699 | argument: any;
700 | }
701 |
702 | declare class BabelNodeTypeAlias extends BabelNode {
703 | type: "TypeAlias";
704 | id: any;
705 | typeParameters: any;
706 | right: any;
707 | }
708 |
709 | declare class BabelNodeTypeAnnotation extends BabelNode {
710 | type: "TypeAnnotation";
711 | typeAnnotation: any;
712 | }
713 |
714 | declare class BabelNodeTypeCastExpression extends BabelNode {
715 | type: "TypeCastExpression";
716 | expression: any;
717 | typeAnnotation: any;
718 | }
719 |
720 | declare class BabelNodeTypeParameterDeclaration extends BabelNode {
721 | type: "TypeParameterDeclaration";
722 | params: any;
723 | }
724 |
725 | declare class BabelNodeTypeParameterInstantiation extends BabelNode {
726 | type: "TypeParameterInstantiation";
727 | params: any;
728 | }
729 |
730 | declare class BabelNodeObjectTypeAnnotation extends BabelNode {
731 | type: "ObjectTypeAnnotation";
732 | properties: any;
733 | indexers: any;
734 | callProperties: any;
735 | }
736 |
737 | declare class BabelNodeObjectTypeCallProperty extends BabelNode {
738 | type: "ObjectTypeCallProperty";
739 | value: any;
740 | }
741 |
742 | declare class BabelNodeObjectTypeIndexer extends BabelNode {
743 | type: "ObjectTypeIndexer";
744 | id: any;
745 | key: any;
746 | value: any;
747 | }
748 |
749 | declare class BabelNodeObjectTypeProperty extends BabelNode {
750 | type: "ObjectTypeProperty";
751 | key: any;
752 | value: any;
753 | }
754 |
755 | declare class BabelNodeQualifiedTypeIdentifier extends BabelNode {
756 | type: "QualifiedTypeIdentifier";
757 | id: any;
758 | qualification: any;
759 | }
760 |
761 | declare class BabelNodeUnionTypeAnnotation extends BabelNode {
762 | type: "UnionTypeAnnotation";
763 | types: any;
764 | }
765 |
766 | declare class BabelNodeVoidTypeAnnotation extends BabelNode {
767 | type: "VoidTypeAnnotation";
768 | }
769 |
770 | declare class BabelNodeJSXAttribute extends BabelNode {
771 | type: "JSXAttribute";
772 | name: BabelNodeJSXIdentifier | BabelNodeJSXNamespacedName;
773 | value?: ?BabelNodeJSXElement | BabelNodeStringLiteral | BabelNodeJSXExpressionContainer;
774 | }
775 |
776 | declare class BabelNodeJSXClosingElement extends BabelNode {
777 | type: "JSXClosingElement";
778 | name: BabelNodeJSXIdentifier | BabelNodeJSXMemberExpression;
779 | }
780 |
781 | declare class BabelNodeJSXElement extends BabelNode {
782 | type: "JSXElement";
783 | openingElement: BabelNodeJSXOpeningElement;
784 | closingElement?: ?BabelNodeJSXClosingElement;
785 | children: any;
786 | selfClosing: any;
787 | }
788 |
789 | declare class BabelNodeJSXEmptyExpression extends BabelNode {
790 | type: "JSXEmptyExpression";
791 | }
792 |
793 | declare class BabelNodeJSXExpressionContainer extends BabelNode {
794 | type: "JSXExpressionContainer";
795 | expression: BabelNodeExpression;
796 | }
797 |
798 | declare class BabelNodeJSXIdentifier extends BabelNode {
799 | type: "JSXIdentifier";
800 | name: string;
801 | }
802 |
803 | declare class BabelNodeJSXMemberExpression extends BabelNode {
804 | type: "JSXMemberExpression";
805 | object: BabelNodeJSXMemberExpression | BabelNodeJSXIdentifier;
806 | property: BabelNodeJSXIdentifier;
807 | }
808 |
809 | declare class BabelNodeJSXNamespacedName extends BabelNode {
810 | type: "JSXNamespacedName";
811 | namespace: BabelNodeJSXIdentifier;
812 | name: BabelNodeJSXIdentifier;
813 | }
814 |
815 | declare class BabelNodeJSXOpeningElement extends BabelNode {
816 | type: "JSXOpeningElement";
817 | name: BabelNodeJSXIdentifier | BabelNodeJSXMemberExpression;
818 | selfClosing?: boolean;
819 | attributes: any;
820 | }
821 |
822 | declare class BabelNodeJSXSpreadAttribute extends BabelNode {
823 | type: "JSXSpreadAttribute";
824 | argument: BabelNodeExpression;
825 | }
826 |
827 | declare class BabelNodeJSXText extends BabelNode {
828 | type: "JSXText";
829 | value: string;
830 | }
831 |
832 | declare class BabelNodeNoop extends BabelNode {
833 | type: "Noop";
834 | }
835 |
836 | declare class BabelNodeParenthesizedExpression extends BabelNode {
837 | type: "ParenthesizedExpression";
838 | expression: BabelNodeExpression;
839 | }
840 |
841 | declare class BabelNodeAwaitExpression extends BabelNode {
842 | type: "AwaitExpression";
843 | argument: BabelNodeExpression;
844 | }
845 |
846 | declare class BabelNodeBindExpression extends BabelNode {
847 | type: "BindExpression";
848 | object: any;
849 | callee: any;
850 | }
851 |
852 | declare class BabelNodeDecorator extends BabelNode {
853 | type: "Decorator";
854 | expression: BabelNodeExpression;
855 | }
856 |
857 | declare class BabelNodeDoExpression extends BabelNode {
858 | type: "DoExpression";
859 | body: BabelNodeBlockStatement;
860 | }
861 |
862 | declare class BabelNodeExportDefaultSpecifier extends BabelNode {
863 | type: "ExportDefaultSpecifier";
864 | exported: BabelNodeIdentifier;
865 | }
866 |
867 | declare class BabelNodeExportNamespaceSpecifier extends BabelNode {
868 | type: "ExportNamespaceSpecifier";
869 | exported: BabelNodeIdentifier;
870 | }
871 |
872 | declare class BabelNodeRestProperty extends BabelNode {
873 | type: "RestProperty";
874 | argument: BabelNodeLVal;
875 | }
876 |
877 | declare class BabelNodeSpreadProperty extends BabelNode {
878 | type: "SpreadProperty";
879 | argument: BabelNodeExpression;
880 | }
881 |
882 | type BabelNodeExpression = BabelNodeArrayExpression | BabelNodeAssignmentExpression | BabelNodeBinaryExpression | BabelNodeCallExpression | BabelNodeConditionalExpression | BabelNodeFunctionExpression | BabelNodeIdentifier | BabelNodeStringLiteral | BabelNodeNumericLiteral | BabelNodeNullLiteral | BabelNodeBooleanLiteral | BabelNodeRegExpLiteral | BabelNodeLogicalExpression | BabelNodeMemberExpression | BabelNodeNewExpression | BabelNodeObjectExpression | BabelNodeSequenceExpression | BabelNodeThisExpression | BabelNodeUnaryExpression | BabelNodeUpdateExpression | BabelNodeArrowFunctionExpression | BabelNodeClassExpression | BabelNodeMetaProperty | BabelNodeSuper | BabelNodeTaggedTemplateExpression | BabelNodeTemplateLiteral | BabelNodeYieldExpression | BabelNodeTypeCastExpression | BabelNodeJSXElement | BabelNodeJSXEmptyExpression | BabelNodeJSXIdentifier | BabelNodeJSXMemberExpression | BabelNodeParenthesizedExpression | BabelNodeAwaitExpression | BabelNodeBindExpression | BabelNodeDoExpression;
883 | type BabelNodeBinary = BabelNodeBinaryExpression | BabelNodeLogicalExpression;
884 | type BabelNodeScopable = BabelNodeBlockStatement | BabelNodeCatchClause | BabelNodeDoWhileStatement | BabelNodeForInStatement | BabelNodeForStatement | BabelNodeFunctionDeclaration | BabelNodeFunctionExpression | BabelNodeProgram | BabelNodeObjectMethod | BabelNodeSwitchStatement | BabelNodeWhileStatement | BabelNodeArrowFunctionExpression | BabelNodeClassDeclaration | BabelNodeClassExpression | BabelNodeForOfStatement | BabelNodeClassMethod;
885 | type BabelNodeBlockParent = BabelNodeBlockStatement | BabelNodeDoWhileStatement | BabelNodeForInStatement | BabelNodeForStatement | BabelNodeFunctionDeclaration | BabelNodeFunctionExpression | BabelNodeProgram | BabelNodeObjectMethod | BabelNodeSwitchStatement | BabelNodeWhileStatement | BabelNodeArrowFunctionExpression | BabelNodeForOfStatement | BabelNodeClassMethod;
886 | type BabelNodeBlock = BabelNodeBlockStatement | BabelNodeProgram;
887 | type BabelNodeStatement = BabelNodeBlockStatement | BabelNodeBreakStatement | BabelNodeContinueStatement | BabelNodeDebuggerStatement | BabelNodeDoWhileStatement | BabelNodeEmptyStatement | BabelNodeExpressionStatement | BabelNodeForInStatement | BabelNodeForStatement | BabelNodeFunctionDeclaration | BabelNodeIfStatement | BabelNodeLabeledStatement | BabelNodeReturnStatement | BabelNodeSwitchStatement | BabelNodeThrowStatement | BabelNodeTryStatement | BabelNodeVariableDeclaration | BabelNodeWhileStatement | BabelNodeWithStatement | BabelNodeClassDeclaration | BabelNodeExportAllDeclaration | BabelNodeExportDefaultDeclaration | BabelNodeExportNamedDeclaration | BabelNodeForOfStatement | BabelNodeImportDeclaration | BabelNodeDeclareClass | BabelNodeDeclareFunction | BabelNodeDeclareInterface | BabelNodeDeclareModule | BabelNodeDeclareTypeAlias | BabelNodeDeclareVariable | BabelNodeInterfaceDeclaration | BabelNodeTypeAlias;
888 | type BabelNodeTerminatorless = BabelNodeBreakStatement | BabelNodeContinueStatement | BabelNodeReturnStatement | BabelNodeThrowStatement | BabelNodeYieldExpression | BabelNodeAwaitExpression;
889 | type BabelNodeCompletionStatement = BabelNodeBreakStatement | BabelNodeContinueStatement | BabelNodeReturnStatement | BabelNodeThrowStatement;
890 | type BabelNodeConditional = BabelNodeConditionalExpression | BabelNodeIfStatement;
891 | type BabelNodeLoop = BabelNodeDoWhileStatement | BabelNodeForInStatement | BabelNodeForStatement | BabelNodeWhileStatement | BabelNodeForOfStatement;
892 | type BabelNodeWhile = BabelNodeDoWhileStatement | BabelNodeWhileStatement;
893 | type BabelNodeExpressionWrapper = BabelNodeExpressionStatement | BabelNodeTypeCastExpression | BabelNodeParenthesizedExpression;
894 | type BabelNodeFor = BabelNodeForInStatement | BabelNodeForStatement | BabelNodeForOfStatement;
895 | type BabelNodeForXStatement = BabelNodeForInStatement | BabelNodeForOfStatement;
896 | type BabelNodeFunction = BabelNodeFunctionDeclaration | BabelNodeFunctionExpression | BabelNodeObjectMethod | BabelNodeArrowFunctionExpression | BabelNodeClassMethod;
897 | type BabelNodeFunctionParent = BabelNodeFunctionDeclaration | BabelNodeFunctionExpression | BabelNodeProgram | BabelNodeObjectMethod | BabelNodeArrowFunctionExpression | BabelNodeClassMethod;
898 | type BabelNodePureish = BabelNodeFunctionDeclaration | BabelNodeFunctionExpression | BabelNodeStringLiteral | BabelNodeNumericLiteral | BabelNodeNullLiteral | BabelNodeBooleanLiteral | BabelNodeArrowFunctionExpression | BabelNodeClassDeclaration | BabelNodeClassExpression;
899 | type BabelNodeDeclaration = BabelNodeFunctionDeclaration | BabelNodeVariableDeclaration | BabelNodeClassDeclaration | BabelNodeExportAllDeclaration | BabelNodeExportDefaultDeclaration | BabelNodeExportNamedDeclaration | BabelNodeImportDeclaration | BabelNodeDeclareClass | BabelNodeDeclareFunction | BabelNodeDeclareInterface | BabelNodeDeclareModule | BabelNodeDeclareTypeAlias | BabelNodeDeclareVariable | BabelNodeInterfaceDeclaration | BabelNodeTypeAlias;
900 | type BabelNodeLVal = BabelNodeIdentifier | BabelNodeMemberExpression | BabelNodeRestElement | BabelNodeAssignmentPattern | BabelNodeArrayPattern | BabelNodeObjectPattern;
901 | type BabelNodeLiteral = BabelNodeStringLiteral | BabelNodeNumericLiteral | BabelNodeNullLiteral | BabelNodeBooleanLiteral | BabelNodeRegExpLiteral | BabelNodeTemplateLiteral;
902 | type BabelNodeImmutable = BabelNodeStringLiteral | BabelNodeNumericLiteral | BabelNodeNullLiteral | BabelNodeBooleanLiteral | BabelNodeJSXAttribute | BabelNodeJSXClosingElement | BabelNodeJSXElement | BabelNodeJSXExpressionContainer | BabelNodeJSXOpeningElement;
903 | type BabelNodeUserWhitespacable = BabelNodeObjectMethod | BabelNodeObjectProperty | BabelNodeObjectTypeCallProperty | BabelNodeObjectTypeIndexer | BabelNodeObjectTypeProperty;
904 | type BabelNodeMethod = BabelNodeObjectMethod | BabelNodeClassMethod;
905 | type BabelNodeObjectMember = BabelNodeObjectMethod | BabelNodeObjectProperty;
906 | type BabelNodeProperty = BabelNodeObjectProperty | BabelNodeClassProperty;
907 | type BabelNodeUnaryLike = BabelNodeUnaryExpression | BabelNodeSpreadElement | BabelNodeRestProperty | BabelNodeSpreadProperty;
908 | type BabelNodePattern = BabelNodeAssignmentPattern | BabelNodeArrayPattern | BabelNodeObjectPattern;
909 | type BabelNodeClass = BabelNodeClassDeclaration | BabelNodeClassExpression;
910 | type BabelNodeModuleDeclaration = BabelNodeExportAllDeclaration | BabelNodeExportDefaultDeclaration | BabelNodeExportNamedDeclaration | BabelNodeImportDeclaration;
911 | type BabelNodeExportDeclaration = BabelNodeExportAllDeclaration | BabelNodeExportDefaultDeclaration | BabelNodeExportNamedDeclaration;
912 | type BabelNodeModuleSpecifier = BabelNodeExportSpecifier | BabelNodeImportDefaultSpecifier | BabelNodeImportNamespaceSpecifier | BabelNodeImportSpecifier | BabelNodeExportDefaultSpecifier | BabelNodeExportNamespaceSpecifier;
913 | type BabelNodeFlow = BabelNodeAnyTypeAnnotation | BabelNodeArrayTypeAnnotation | BabelNodeBooleanTypeAnnotation | BabelNodeBooleanLiteralTypeAnnotation | BabelNodeNullLiteralTypeAnnotation | BabelNodeClassImplements | BabelNodeClassProperty | BabelNodeDeclareClass | BabelNodeDeclareFunction | BabelNodeDeclareInterface | BabelNodeDeclareModule | BabelNodeDeclareTypeAlias | BabelNodeDeclareVariable | BabelNodeExistentialTypeParam | BabelNodeFunctionTypeAnnotation | BabelNodeFunctionTypeParam | BabelNodeGenericTypeAnnotation | BabelNodeInterfaceExtends | BabelNodeInterfaceDeclaration | BabelNodeIntersectionTypeAnnotation | BabelNodeMixedTypeAnnotation | BabelNodeNullableTypeAnnotation | BabelNodeNumericLiteralTypeAnnotation | BabelNodeNumberTypeAnnotation | BabelNodeStringLiteralTypeAnnotation | BabelNodeStringTypeAnnotation | BabelNodeThisTypeAnnotation | BabelNodeTupleTypeAnnotation | BabelNodeTypeofTypeAnnotation | BabelNodeTypeAlias | BabelNodeTypeAnnotation | BabelNodeTypeCastExpression | BabelNodeTypeParameterDeclaration | BabelNodeTypeParameterInstantiation | BabelNodeObjectTypeAnnotation | BabelNodeObjectTypeCallProperty | BabelNodeObjectTypeIndexer | BabelNodeObjectTypeProperty | BabelNodeQualifiedTypeIdentifier | BabelNodeUnionTypeAnnotation | BabelNodeVoidTypeAnnotation;
914 | type BabelNodeFlowBaseAnnotation = BabelNodeAnyTypeAnnotation | BabelNodeBooleanTypeAnnotation | BabelNodeNullLiteralTypeAnnotation | BabelNodeMixedTypeAnnotation | BabelNodeNumberTypeAnnotation | BabelNodeStringTypeAnnotation | BabelNodeThisTypeAnnotation | BabelNodeVoidTypeAnnotation;
915 | type BabelNodeFlowDeclaration = BabelNodeDeclareClass | BabelNodeDeclareFunction | BabelNodeDeclareInterface | BabelNodeDeclareModule | BabelNodeDeclareTypeAlias | BabelNodeDeclareVariable | BabelNodeInterfaceDeclaration | BabelNodeTypeAlias;
916 | type BabelNodeJSX = BabelNodeJSXAttribute | BabelNodeJSXClosingElement | BabelNodeJSXElement | BabelNodeJSXEmptyExpression | BabelNodeJSXExpressionContainer | BabelNodeJSXIdentifier | BabelNodeJSXMemberExpression | BabelNodeJSXNamespacedName | BabelNodeJSXOpeningElement | BabelNodeJSXSpreadAttribute | BabelNodeJSXText;
917 |
918 | declare module "babel-types" {
919 | declare function arrayExpression(elements?: any): BabelNodeArrayExpression;
920 | declare function assignmentExpression(operator: string, left: BabelNodeLVal, right: BabelNodeExpression): BabelNodeAssignmentExpression;
921 | declare function binaryExpression(operator: "+" | "-" | "/" | "%" | "*" | "**" | "&" | "|" | ">>" | ">>>" | "<<" | "^" | "==" | "===" | "!=" | "!==" | "in" | "instanceof" | ">" | "<" | ">=" | "<=", left: BabelNodeExpression, right: BabelNodeExpression): BabelNodeBinaryExpression;
922 | declare function directive(value: BabelNodeDirectiveLiteral): BabelNodeDirective;
923 | declare function directiveLiteral(value: string): BabelNodeDirectiveLiteral;
924 | declare function blockStatement(directives?: any, body: any): BabelNodeBlockStatement;
925 | declare function breakStatement(label?: ?BabelNodeIdentifier): BabelNodeBreakStatement;
926 | declare function callExpression(callee: BabelNodeExpression, _arguments: any): BabelNodeCallExpression;
927 | declare function catchClause(param: BabelNodeIdentifier, body: BabelNodeBlockStatement): BabelNodeCatchClause;
928 | declare function conditionalExpression(test: BabelNodeExpression, consequent: BabelNodeExpression, alternate: BabelNodeExpression): BabelNodeConditionalExpression;
929 | declare function continueStatement(label?: ?BabelNodeIdentifier): BabelNodeContinueStatement;
930 | declare function debuggerStatement(): BabelNodeDebuggerStatement;
931 | declare function doWhileStatement(test: BabelNodeExpression, body: BabelNodeStatement): BabelNodeDoWhileStatement;
932 | declare function emptyStatement(): BabelNodeEmptyStatement;
933 | declare function expressionStatement(expression: BabelNodeExpression): BabelNodeExpressionStatement;
934 | declare function file(program: BabelNodeProgram, comments: any, tokens: any): BabelNodeFile;
935 | declare function forInStatement(left: BabelNodeVariableDeclaration | BabelNodeLVal, right: BabelNodeExpression, body: BabelNodeStatement): BabelNodeForInStatement;
936 | declare function forStatement(init?: ?BabelNodeVariableDeclaration | BabelNodeExpression, test?: ?BabelNodeExpression, update?: ?BabelNodeExpression, body: BabelNodeStatement): BabelNodeForStatement;
937 | declare function functionDeclaration(id: BabelNodeIdentifier, params: any, body: BabelNodeBlockStatement, generator?: boolean, async?: boolean, returnType: any, typeParameters: any): BabelNodeFunctionDeclaration;
938 | declare function functionExpression(id?: ?BabelNodeIdentifier, params: any, body: BabelNodeBlockStatement, generator?: boolean, async?: boolean, returnType: any, typeParameters: any): BabelNodeFunctionExpression;
939 | declare function identifier(name: any, typeAnnotation: any): BabelNodeIdentifier;
940 | declare function ifStatement(test: BabelNodeExpression, consequent: BabelNodeStatement, alternate?: ?BabelNodeStatement): BabelNodeIfStatement;
941 | declare function labeledStatement(label: BabelNodeIdentifier, body: BabelNodeStatement): BabelNodeLabeledStatement;
942 | declare function stringLiteral(value: string): BabelNodeStringLiteral;
943 | declare function numericLiteral(value: number): BabelNodeNumericLiteral;
944 | declare function nullLiteral(): BabelNodeNullLiteral;
945 | declare function booleanLiteral(value: boolean): BabelNodeBooleanLiteral;
946 | declare function regExpLiteral(pattern: string, flags?: string): BabelNodeRegExpLiteral;
947 | declare function logicalExpression(operator: "||" | "&&", left: BabelNodeExpression, right: BabelNodeExpression): BabelNodeLogicalExpression;
948 | declare function memberExpression(object: BabelNodeExpression, property: any, computed?: boolean): BabelNodeMemberExpression;
949 | declare function newExpression(callee: BabelNodeExpression, _arguments: any): BabelNodeNewExpression;
950 | declare function program(directives?: any, body: any): BabelNodeProgram;
951 | declare function objectExpression(properties: any): BabelNodeObjectExpression;
952 | declare function objectMethod(kind?: any, computed?: boolean, key: any, decorators: any, body: BabelNodeBlockStatement, generator?: boolean, async?: boolean, params: any, returnType: any, typeParameters: any): BabelNodeObjectMethod;
953 | declare function objectProperty(computed?: boolean, key: any, value: BabelNodeExpression, shorthand?: boolean, decorators?: any): BabelNodeObjectProperty;
954 | declare function restElement(argument: BabelNodeLVal, typeAnnotation: any): BabelNodeRestElement;
955 | declare function returnStatement(argument?: ?BabelNodeExpression): BabelNodeReturnStatement;
956 | declare function sequenceExpression(expressions: any): BabelNodeSequenceExpression;
957 | declare function switchCase(test?: ?BabelNodeExpression, consequent: any): BabelNodeSwitchCase;
958 | declare function switchStatement(discriminant: BabelNodeExpression, cases: any): BabelNodeSwitchStatement;
959 | declare function thisExpression(): BabelNodeThisExpression;
960 | declare function throwStatement(argument: BabelNodeExpression): BabelNodeThrowStatement;
961 | declare function tryStatement(body: BabelNodeBlockStatement, handler?: any, finalizer?: ?BabelNodeBlockStatement, block: any): BabelNodeTryStatement;
962 | declare function unaryExpression(prefix?: boolean, argument: BabelNodeExpression, operator: "void" | "delete" | "!" | "+" | "-" | "++" | "--" | "~" | "typeof"): BabelNodeUnaryExpression;
963 | declare function updateExpression(prefix?: boolean, argument: BabelNodeExpression, operator: "++" | "--"): BabelNodeUpdateExpression;
964 | declare function variableDeclaration(kind: any, declarations: any): BabelNodeVariableDeclaration;
965 | declare function variableDeclarator(id: BabelNodeLVal, init?: ?BabelNodeExpression): BabelNodeVariableDeclarator;
966 | declare function whileStatement(test: BabelNodeExpression, body: BabelNodeBlockStatement | BabelNodeStatement): BabelNodeWhileStatement;
967 | declare function withStatement(object: any, body: BabelNodeBlockStatement | BabelNodeStatement): BabelNodeWithStatement;
968 | declare function assignmentPattern(left: BabelNodeIdentifier, right: BabelNodeExpression): BabelNodeAssignmentPattern;
969 | declare function arrayPattern(elements: any, typeAnnotation: any): BabelNodeArrayPattern;
970 | declare function arrowFunctionExpression(params: any, body: BabelNodeBlockStatement | BabelNodeExpression, async?: boolean, returnType: any): BabelNodeArrowFunctionExpression;
971 | declare function classBody(body: any): BabelNodeClassBody;
972 | declare function classDeclaration(id: BabelNodeIdentifier, body: BabelNodeClassBody, superClass?: ?BabelNodeExpression, decorators: any, mixins: any, typeParameters: any, superTypeParameters: any, _implements: any): BabelNodeClassDeclaration;
973 | declare function classExpression(id?: ?BabelNodeIdentifier, body: BabelNodeClassBody, superClass?: ?BabelNodeExpression, decorators: any, mixins: any, typeParameters: any, superTypeParameters: any, _implements: any): BabelNodeClassExpression;
974 | declare function exportAllDeclaration(source: BabelNodeStringLiteral): BabelNodeExportAllDeclaration;
975 | declare function exportDefaultDeclaration(declaration: BabelNodeFunctionDeclaration | BabelNodeClassDeclaration | BabelNodeExpression): BabelNodeExportDefaultDeclaration;
976 | declare function exportNamedDeclaration(declaration?: ?BabelNodeDeclaration, specifiers: any, source?: ?BabelNodeStringLiteral): BabelNodeExportNamedDeclaration;
977 | declare function exportSpecifier(local: BabelNodeIdentifier, imported: BabelNodeIdentifier, exported: any): BabelNodeExportSpecifier;
978 | declare function forOfStatement(left: BabelNodeVariableDeclaration | BabelNodeLVal, right: BabelNodeExpression, body: BabelNodeStatement): BabelNodeForOfStatement;
979 | declare function importDeclaration(specifiers: any, source: BabelNodeStringLiteral): BabelNodeImportDeclaration;
980 | declare function importDefaultSpecifier(local: BabelNodeIdentifier): BabelNodeImportDefaultSpecifier;
981 | declare function importNamespaceSpecifier(local: BabelNodeIdentifier): BabelNodeImportNamespaceSpecifier;
982 | declare function importSpecifier(local: BabelNodeIdentifier, imported: BabelNodeIdentifier): BabelNodeImportSpecifier;
983 | declare function metaProperty(meta: string, property: string): BabelNodeMetaProperty;
984 | declare function classMethod(kind?: any, computed?: boolean, _static?: boolean, key: any, params: any, body: BabelNodeBlockStatement, generator?: boolean, async?: boolean, decorators: any, returnType: any, typeParameters: any): BabelNodeClassMethod;
985 | declare function objectPattern(properties: any, typeAnnotation: any): BabelNodeObjectPattern;
986 | declare function spreadElement(argument: BabelNodeExpression): BabelNodeSpreadElement;
987 | declare function taggedTemplateExpression(tag: BabelNodeExpression, quasi: BabelNodeTemplateLiteral): BabelNodeTaggedTemplateExpression;
988 | declare function templateElement(value: any, tail?: boolean): BabelNodeTemplateElement;
989 | declare function templateLiteral(quasis: any, expressions: any): BabelNodeTemplateLiteral;
990 | declare function yieldExpression(delegate?: boolean, argument?: ?BabelNodeExpression): BabelNodeYieldExpression;
991 | declare function anyTypeAnnotation(): BabelNodeAnyTypeAnnotation;
992 | declare function arrayTypeAnnotation(elementType: any): BabelNodeArrayTypeAnnotation;
993 | declare function booleanTypeAnnotation(): BabelNodeBooleanTypeAnnotation;
994 | declare function booleanLiteralTypeAnnotation(): BabelNodeBooleanLiteralTypeAnnotation;
995 | declare function nullLiteralTypeAnnotation(): BabelNodeNullLiteralTypeAnnotation;
996 | declare function classImplements(id: any, typeParameters: any): BabelNodeClassImplements;
997 | declare function classProperty(key: any, value: any, typeAnnotation: any, decorators: any): BabelNodeClassProperty;
998 | declare function declareClass(id: any, typeParameters: any, _extends: any, body: any): BabelNodeDeclareClass;
999 | declare function declareFunction(id: any): BabelNodeDeclareFunction;
1000 | declare function declareInterface(id: any, typeParameters: any, _extends: any, body: any): BabelNodeDeclareInterface;
1001 | declare function declareModule(id: any, body: any): BabelNodeDeclareModule;
1002 | declare function declareTypeAlias(id: any, typeParameters: any, right: any): BabelNodeDeclareTypeAlias;
1003 | declare function declareVariable(id: any): BabelNodeDeclareVariable;
1004 | declare function existentialTypeParam(): BabelNodeExistentialTypeParam;
1005 | declare function functionTypeAnnotation(typeParameters: any, params: any, rest: any, returnType: any): BabelNodeFunctionTypeAnnotation;
1006 | declare function functionTypeParam(name: any, typeAnnotation: any): BabelNodeFunctionTypeParam;
1007 | declare function genericTypeAnnotation(id: any, typeParameters: any): BabelNodeGenericTypeAnnotation;
1008 | declare function interfaceExtends(id: any, typeParameters: any): BabelNodeInterfaceExtends;
1009 | declare function interfaceDeclaration(id: any, typeParameters: any, _extends: any, body: any): BabelNodeInterfaceDeclaration;
1010 | declare function intersectionTypeAnnotation(types: any): BabelNodeIntersectionTypeAnnotation;
1011 | declare function mixedTypeAnnotation(): BabelNodeMixedTypeAnnotation;
1012 | declare function nullableTypeAnnotation(typeAnnotation: any): BabelNodeNullableTypeAnnotation;
1013 | declare function numericLiteralTypeAnnotation(): BabelNodeNumericLiteralTypeAnnotation;
1014 | declare function numberTypeAnnotation(): BabelNodeNumberTypeAnnotation;
1015 | declare function stringLiteralTypeAnnotation(): BabelNodeStringLiteralTypeAnnotation;
1016 | declare function stringTypeAnnotation(): BabelNodeStringTypeAnnotation;
1017 | declare function thisTypeAnnotation(): BabelNodeThisTypeAnnotation;
1018 | declare function tupleTypeAnnotation(types: any): BabelNodeTupleTypeAnnotation;
1019 | declare function typeofTypeAnnotation(argument: any): BabelNodeTypeofTypeAnnotation;
1020 | declare function typeAlias(id: any, typeParameters: any, right: any): BabelNodeTypeAlias;
1021 | declare function typeAnnotation(typeAnnotation: any): BabelNodeTypeAnnotation;
1022 | declare function typeCastExpression(expression: any, typeAnnotation: any): BabelNodeTypeCastExpression;
1023 | declare function typeParameterDeclaration(params: any): BabelNodeTypeParameterDeclaration;
1024 | declare function typeParameterInstantiation(params: any): BabelNodeTypeParameterInstantiation;
1025 | declare function objectTypeAnnotation(properties: any, indexers: any, callProperties: any): BabelNodeObjectTypeAnnotation;
1026 | declare function objectTypeCallProperty(value: any): BabelNodeObjectTypeCallProperty;
1027 | declare function objectTypeIndexer(id: any, key: any, value: any): BabelNodeObjectTypeIndexer;
1028 | declare function objectTypeProperty(key: any, value: any): BabelNodeObjectTypeProperty;
1029 | declare function qualifiedTypeIdentifier(id: any, qualification: any): BabelNodeQualifiedTypeIdentifier;
1030 | declare function unionTypeAnnotation(types: any): BabelNodeUnionTypeAnnotation;
1031 | declare function voidTypeAnnotation(): BabelNodeVoidTypeAnnotation;
1032 | declare function jSXAttribute(name: BabelNodeJSXIdentifier | BabelNodeJSXNamespacedName, value?: ?BabelNodeJSXElement | BabelNodeStringLiteral | BabelNodeJSXExpressionContainer): BabelNodeJSXAttribute;
1033 | declare function jSXClosingElement(name: BabelNodeJSXIdentifier | BabelNodeJSXMemberExpression): BabelNodeJSXClosingElement;
1034 | declare function jSXElement(openingElement: BabelNodeJSXOpeningElement, closingElement?: ?BabelNodeJSXClosingElement, children: any, selfClosing: any): BabelNodeJSXElement;
1035 | declare function jSXEmptyExpression(): BabelNodeJSXEmptyExpression;
1036 | declare function jSXExpressionContainer(expression: BabelNodeExpression): BabelNodeJSXExpressionContainer;
1037 | declare function jSXIdentifier(name: string): BabelNodeJSXIdentifier;
1038 | declare function jSXMemberExpression(object: BabelNodeJSXMemberExpression | BabelNodeJSXIdentifier, property: BabelNodeJSXIdentifier): BabelNodeJSXMemberExpression;
1039 | declare function jSXNamespacedName(namespace: BabelNodeJSXIdentifier, name: BabelNodeJSXIdentifier): BabelNodeJSXNamespacedName;
1040 | declare function jSXOpeningElement(name: BabelNodeJSXIdentifier | BabelNodeJSXMemberExpression, selfClosing?: boolean, attributes: any): BabelNodeJSXOpeningElement;
1041 | declare function jSXSpreadAttribute(argument: BabelNodeExpression): BabelNodeJSXSpreadAttribute;
1042 | declare function jSXText(value: string): BabelNodeJSXText;
1043 | declare function noop(): BabelNodeNoop;
1044 | declare function parenthesizedExpression(expression: BabelNodeExpression): BabelNodeParenthesizedExpression;
1045 | declare function awaitExpression(argument: BabelNodeExpression): BabelNodeAwaitExpression;
1046 | declare function bindExpression(object: any, callee: any): BabelNodeBindExpression;
1047 | declare function decorator(expression: BabelNodeExpression): BabelNodeDecorator;
1048 | declare function doExpression(body: BabelNodeBlockStatement): BabelNodeDoExpression;
1049 | declare function exportDefaultSpecifier(exported: BabelNodeIdentifier): BabelNodeExportDefaultSpecifier;
1050 | declare function exportNamespaceSpecifier(exported: BabelNodeIdentifier): BabelNodeExportNamespaceSpecifier;
1051 | declare function restProperty(argument: BabelNodeLVal): BabelNodeRestProperty;
1052 | declare function spreadProperty(argument: BabelNodeExpression): BabelNodeSpreadProperty;
1053 | declare function isArrayExpression(node: Object, opts?: Object): boolean;
1054 | declare function isAssignmentExpression(node: Object, opts?: Object): boolean;
1055 | declare function isBinaryExpression(node: Object, opts?: Object): boolean;
1056 | declare function isDirective(node: Object, opts?: Object): boolean;
1057 | declare function isDirectiveLiteral(node: Object, opts?: Object): boolean;
1058 | declare function isBlockStatement(node: Object, opts?: Object): boolean;
1059 | declare function isBreakStatement(node: Object, opts?: Object): boolean;
1060 | declare function isCallExpression(node: Object, opts?: Object): boolean;
1061 | declare function isCatchClause(node: Object, opts?: Object): boolean;
1062 | declare function isConditionalExpression(node: Object, opts?: Object): boolean;
1063 | declare function isContinueStatement(node: Object, opts?: Object): boolean;
1064 | declare function isDebuggerStatement(node: Object, opts?: Object): boolean;
1065 | declare function isDoWhileStatement(node: Object, opts?: Object): boolean;
1066 | declare function isEmptyStatement(node: Object, opts?: Object): boolean;
1067 | declare function isExpressionStatement(node: Object, opts?: Object): boolean;
1068 | declare function isFile(node: Object, opts?: Object): boolean;
1069 | declare function isForInStatement(node: Object, opts?: Object): boolean;
1070 | declare function isForStatement(node: Object, opts?: Object): boolean;
1071 | declare function isFunctionDeclaration(node: Object, opts?: Object): boolean;
1072 | declare function isFunctionExpression(node: Object, opts?: Object): boolean;
1073 | declare function isIdentifier(node: Object, opts?: Object): boolean;
1074 | declare function isIfStatement(node: Object, opts?: Object): boolean;
1075 | declare function isLabeledStatement(node: Object, opts?: Object): boolean;
1076 | declare function isStringLiteral(node: Object, opts?: Object): boolean;
1077 | declare function isNumericLiteral(node: Object, opts?: Object): boolean;
1078 | declare function isNullLiteral(node: Object, opts?: Object): boolean;
1079 | declare function isBooleanLiteral(node: Object, opts?: Object): boolean;
1080 | declare function isRegExpLiteral(node: Object, opts?: Object): boolean;
1081 | declare function isLogicalExpression(node: Object, opts?: Object): boolean;
1082 | declare function isMemberExpression(node: Object, opts?: Object): boolean;
1083 | declare function isNewExpression(node: Object, opts?: Object): boolean;
1084 | declare function isProgram(node: Object, opts?: Object): boolean;
1085 | declare function isObjectExpression(node: Object, opts?: Object): boolean;
1086 | declare function isObjectMethod(node: Object, opts?: Object): boolean;
1087 | declare function isObjectProperty(node: Object, opts?: Object): boolean;
1088 | declare function isRestElement(node: Object, opts?: Object): boolean;
1089 | declare function isReturnStatement(node: Object, opts?: Object): boolean;
1090 | declare function isSequenceExpression(node: Object, opts?: Object): boolean;
1091 | declare function isSwitchCase(node: Object, opts?: Object): boolean;
1092 | declare function isSwitchStatement(node: Object, opts?: Object): boolean;
1093 | declare function isThisExpression(node: Object, opts?: Object): boolean;
1094 | declare function isThrowStatement(node: Object, opts?: Object): boolean;
1095 | declare function isTryStatement(node: Object, opts?: Object): boolean;
1096 | declare function isUnaryExpression(node: Object, opts?: Object): boolean;
1097 | declare function isUpdateExpression(node: Object, opts?: Object): boolean;
1098 | declare function isVariableDeclaration(node: Object, opts?: Object): boolean;
1099 | declare function isVariableDeclarator(node: Object, opts?: Object): boolean;
1100 | declare function isWhileStatement(node: Object, opts?: Object): boolean;
1101 | declare function isWithStatement(node: Object, opts?: Object): boolean;
1102 | declare function isAssignmentPattern(node: Object, opts?: Object): boolean;
1103 | declare function isArrayPattern(node: Object, opts?: Object): boolean;
1104 | declare function isArrowFunctionExpression(node: Object, opts?: Object): boolean;
1105 | declare function isClassBody(node: Object, opts?: Object): boolean;
1106 | declare function isClassDeclaration(node: Object, opts?: Object): boolean;
1107 | declare function isClassExpression(node: Object, opts?: Object): boolean;
1108 | declare function isExportAllDeclaration(node: Object, opts?: Object): boolean;
1109 | declare function isExportDefaultDeclaration(node: Object, opts?: Object): boolean;
1110 | declare function isExportNamedDeclaration(node: Object, opts?: Object): boolean;
1111 | declare function isExportSpecifier(node: Object, opts?: Object): boolean;
1112 | declare function isForOfStatement(node: Object, opts?: Object): boolean;
1113 | declare function isImportDeclaration(node: Object, opts?: Object): boolean;
1114 | declare function isImportDefaultSpecifier(node: Object, opts?: Object): boolean;
1115 | declare function isImportNamespaceSpecifier(node: Object, opts?: Object): boolean;
1116 | declare function isImportSpecifier(node: Object, opts?: Object): boolean;
1117 | declare function isMetaProperty(node: Object, opts?: Object): boolean;
1118 | declare function isClassMethod(node: Object, opts?: Object): boolean;
1119 | declare function isObjectPattern(node: Object, opts?: Object): boolean;
1120 | declare function isSpreadElement(node: Object, opts?: Object): boolean;
1121 | declare function isSuper(node: Object, opts?: Object): boolean;
1122 | declare function isTaggedTemplateExpression(node: Object, opts?: Object): boolean;
1123 | declare function isTemplateElement(node: Object, opts?: Object): boolean;
1124 | declare function isTemplateLiteral(node: Object, opts?: Object): boolean;
1125 | declare function isYieldExpression(node: Object, opts?: Object): boolean;
1126 | declare function isAnyTypeAnnotation(node: Object, opts?: Object): boolean;
1127 | declare function isArrayTypeAnnotation(node: Object, opts?: Object): boolean;
1128 | declare function isBooleanTypeAnnotation(node: Object, opts?: Object): boolean;
1129 | declare function isBooleanLiteralTypeAnnotation(node: Object, opts?: Object): boolean;
1130 | declare function isNullLiteralTypeAnnotation(node: Object, opts?: Object): boolean;
1131 | declare function isClassImplements(node: Object, opts?: Object): boolean;
1132 | declare function isClassProperty(node: Object, opts?: Object): boolean;
1133 | declare function isDeclareClass(node: Object, opts?: Object): boolean;
1134 | declare function isDeclareFunction(node: Object, opts?: Object): boolean;
1135 | declare function isDeclareInterface(node: Object, opts?: Object): boolean;
1136 | declare function isDeclareModule(node: Object, opts?: Object): boolean;
1137 | declare function isDeclareTypeAlias(node: Object, opts?: Object): boolean;
1138 | declare function isDeclareVariable(node: Object, opts?: Object): boolean;
1139 | declare function isExistentialTypeParam(node: Object, opts?: Object): boolean;
1140 | declare function isFunctionTypeAnnotation(node: Object, opts?: Object): boolean;
1141 | declare function isFunctionTypeParam(node: Object, opts?: Object): boolean;
1142 | declare function isGenericTypeAnnotation(node: Object, opts?: Object): boolean;
1143 | declare function isInterfaceExtends(node: Object, opts?: Object): boolean;
1144 | declare function isInterfaceDeclaration(node: Object, opts?: Object): boolean;
1145 | declare function isIntersectionTypeAnnotation(node: Object, opts?: Object): boolean;
1146 | declare function isMixedTypeAnnotation(node: Object, opts?: Object): boolean;
1147 | declare function isNullableTypeAnnotation(node: Object, opts?: Object): boolean;
1148 | declare function isNumericLiteralTypeAnnotation(node: Object, opts?: Object): boolean;
1149 | declare function isNumberTypeAnnotation(node: Object, opts?: Object): boolean;
1150 | declare function isStringLiteralTypeAnnotation(node: Object, opts?: Object): boolean;
1151 | declare function isStringTypeAnnotation(node: Object, opts?: Object): boolean;
1152 | declare function isThisTypeAnnotation(node: Object, opts?: Object): boolean;
1153 | declare function isTupleTypeAnnotation(node: Object, opts?: Object): boolean;
1154 | declare function isTypeofTypeAnnotation(node: Object, opts?: Object): boolean;
1155 | declare function isTypeAlias(node: Object, opts?: Object): boolean;
1156 | declare function isTypeAnnotation(node: Object, opts?: Object): boolean;
1157 | declare function isTypeCastExpression(node: Object, opts?: Object): boolean;
1158 | declare function isTypeParameterDeclaration(node: Object, opts?: Object): boolean;
1159 | declare function isTypeParameterInstantiation(node: Object, opts?: Object): boolean;
1160 | declare function isObjectTypeAnnotation(node: Object, opts?: Object): boolean;
1161 | declare function isObjectTypeCallProperty(node: Object, opts?: Object): boolean;
1162 | declare function isObjectTypeIndexer(node: Object, opts?: Object): boolean;
1163 | declare function isObjectTypeProperty(node: Object, opts?: Object): boolean;
1164 | declare function isQualifiedTypeIdentifier(node: Object, opts?: Object): boolean;
1165 | declare function isUnionTypeAnnotation(node: Object, opts?: Object): boolean;
1166 | declare function isVoidTypeAnnotation(node: Object, opts?: Object): boolean;
1167 | declare function isJSXAttribute(node: Object, opts?: Object): boolean;
1168 | declare function isJSXClosingElement(node: Object, opts?: Object): boolean;
1169 | declare function isJSXElement(node: Object, opts?: Object): boolean;
1170 | declare function isJSXEmptyExpression(node: Object, opts?: Object): boolean;
1171 | declare function isJSXExpressionContainer(node: Object, opts?: Object): boolean;
1172 | declare function isJSXIdentifier(node: Object, opts?: Object): boolean;
1173 | declare function isJSXMemberExpression(node: Object, opts?: Object): boolean;
1174 | declare function isJSXNamespacedName(node: Object, opts?: Object): boolean;
1175 | declare function isJSXOpeningElement(node: Object, opts?: Object): boolean;
1176 | declare function isJSXSpreadAttribute(node: Object, opts?: Object): boolean;
1177 | declare function isJSXText(node: Object, opts?: Object): boolean;
1178 | declare function isNoop(node: Object, opts?: Object): boolean;
1179 | declare function isParenthesizedExpression(node: Object, opts?: Object): boolean;
1180 | declare function isAwaitExpression(node: Object, opts?: Object): boolean;
1181 | declare function isBindExpression(node: Object, opts?: Object): boolean;
1182 | declare function isDecorator(node: Object, opts?: Object): boolean;
1183 | declare function isDoExpression(node: Object, opts?: Object): boolean;
1184 | declare function isExportDefaultSpecifier(node: Object, opts?: Object): boolean;
1185 | declare function isExportNamespaceSpecifier(node: Object, opts?: Object): boolean;
1186 | declare function isRestProperty(node: Object, opts?: Object): boolean;
1187 | declare function isSpreadProperty(node: Object, opts?: Object): boolean;
1188 | declare function isExpression(node: Object, opts?: Object): boolean;
1189 | declare function isBinary(node: Object, opts?: Object): boolean;
1190 | declare function isScopable(node: Object, opts?: Object): boolean;
1191 | declare function isBlockParent(node: Object, opts?: Object): boolean;
1192 | declare function isBlock(node: Object, opts?: Object): boolean;
1193 | declare function isStatement(node: Object, opts?: Object): boolean;
1194 | declare function isTerminatorless(node: Object, opts?: Object): boolean;
1195 | declare function isCompletionStatement(node: Object, opts?: Object): boolean;
1196 | declare function isConditional(node: Object, opts?: Object): boolean;
1197 | declare function isLoop(node: Object, opts?: Object): boolean;
1198 | declare function isWhile(node: Object, opts?: Object): boolean;
1199 | declare function isExpressionWrapper(node: Object, opts?: Object): boolean;
1200 | declare function isFor(node: Object, opts?: Object): boolean;
1201 | declare function isForXStatement(node: Object, opts?: Object): boolean;
1202 | declare function isFunction(node: Object, opts?: Object): boolean;
1203 | declare function isFunctionParent(node: Object, opts?: Object): boolean;
1204 | declare function isPureish(node: Object, opts?: Object): boolean;
1205 | declare function isDeclaration(node: Object, opts?: Object): boolean;
1206 | declare function isLVal(node: Object, opts?: Object): boolean;
1207 | declare function isLiteral(node: Object, opts?: Object): boolean;
1208 | declare function isImmutable(node: Object, opts?: Object): boolean;
1209 | declare function isUserWhitespacable(node: Object, opts?: Object): boolean;
1210 | declare function isMethod(node: Object, opts?: Object): boolean;
1211 | declare function isObjectMember(node: Object, opts?: Object): boolean;
1212 | declare function isProperty(node: Object, opts?: Object): boolean;
1213 | declare function isUnaryLike(node: Object, opts?: Object): boolean;
1214 | declare function isPattern(node: Object, opts?: Object): boolean;
1215 | declare function isClass(node: Object, opts?: Object): boolean;
1216 | declare function isModuleDeclaration(node: Object, opts?: Object): boolean;
1217 | declare function isExportDeclaration(node: Object, opts?: Object): boolean;
1218 | declare function isModuleSpecifier(node: Object, opts?: Object): boolean;
1219 | declare function isFlow(node: Object, opts?: Object): boolean;
1220 | declare function isFlowBaseAnnotation(node: Object, opts?: Object): boolean;
1221 | declare function isFlowDeclaration(node: Object, opts?: Object): boolean;
1222 | declare function isJSX(node: Object, opts?: Object): boolean;
1223 | declare function isNumberLiteral(node: Object, opts?: Object): boolean;
1224 | declare function isRegexLiteral(node: Object, opts?: Object): boolean;
1225 | declare function isReferencedIdentifier(node: Object, opts?: Object): boolean;
1226 | declare function isReferencedMemberExpression(node: Object, opts?: Object): boolean;
1227 | declare function isBindingIdentifier(node: Object, opts?: Object): boolean;
1228 | declare function isScope(node: Object, opts?: Object): boolean;
1229 | declare function isReferenced(node: Object, opts?: Object): boolean;
1230 | declare function isBlockScoped(node: Object, opts?: Object): boolean;
1231 | declare function isVar(node: Object, opts?: Object): boolean;
1232 | declare function isUser(node: Object, opts?: Object): boolean;
1233 | declare function isGenerated(node: Object, opts?: Object): boolean;
1234 | declare function isPure(node: Object, opts?: Object): boolean;
1235 | }
1236 |
--------------------------------------------------------------------------------