Skip to content

Commit 25b86e9

Browse files
kimusakuescapinbotrenovate-botrenovate[bot]
authored
feat(visitors): improve type checking for general-callback functions (#202)
* fix(testing): use mocha, chai and nyc instead of jest * chore(deps): pin dependencies * chore(deps): remove tslib from dependencies (#175) * chore(deps): update typescript-eslint monorepo to v2.33.0 (#176) Co-authored-by: Renovate Bot <[email protected]> * chore(deps): update dependency @types/deasync to v0.1.1 * chore(deps): update dependency @types/js-yaml to v3.12.4 * chore(deps): update dependency @types/eslint to v6.8.1 * chore(deps): update dependency @types/ncp to v2.0.4 * chore(deps): update dependency @types/lodash to v4.14.151 (#181) Co-authored-by: Renovate Bot <[email protected]> * chore(deps): lock file maintenance * chore(deps): update dependency lint-staged to v10.2.4 * chore(deps): update typescript-eslint monorepo to v2.34.0 * chore(deps): update dependency @types/uuid to v8 * chore(deps): update dependency @types/lodash to v4.14.152 * chore(deps): update dependency @types/prettier to v2.0.1 * chore(deps): update typescript-eslint monorepo to v3 (major) (#191) * chore(deps): update typescript-eslint monorepo to v3 * chore(*): update submodules * chore(*): disable rule '@typescript-eslint/camelcase' * chore(*): update eslint rules * disable '@typescript-eslint/explicit-module-boundary-types' * enable '@typescript-eslint/naming-convention' Co-authored-by: Renovate Bot <[email protected]> Co-authored-by: Kosaku Kimura <[email protected]> * chore(deps): update dependency lint-staged to v10.2.6 * chore(deps): update dependency eslint to v7.1.0 * chore(deps): update dependency mocha to v7.2.0 * chore(deps): lock file maintenance * chore(deps): update typescript-eslint monorepo to v3.0.1 * chore(deps): update dependency @types/lodash to v4.14.153 * chore(deps): update typescript-eslint monorepo to v3.0.2 * chore(deps): update dependency ts-node to v8.10.2 * chore(deps): update dependency lint-staged to v10.2.7 * chore(deps): update dependency @types/lodash to v4.14.154 * chore(deps): lock file maintenance * chore(deps): update dependency nyc to v15.1.0 * chore(deps): update typescript-eslint monorepo to v3.1.0 * chore(deps): update dependency @types/babel__traverse to v7.0.12 * chore(deps): update dependency @types/lodash to v4.14.155 * chore(deps): update dependency lint-staged to v10.2.8 * chore(deps): update dependency lint-staged to v10.2.9 * chore(deps): update dependency eslint to v7.2.0 * chore(deps): update dependency @types/mkdirp to v1.0.1 * chore(deps): lock file maintenance * chore(deps): update typescript-eslint monorepo to v3.2.0 * chore(deps): update dependency mocha to v8 * chore(deps): update dependency mocha to v8.0.1 * chore(deps): update dependency lint-staged to v10.2.10 * chore(deps): update dependency @types/eslint to v7 * chore(deps): lock file maintenance * chore(deps): lock file maintenance * chore(deps): update dependency eslint-plugin-prettier to v3.1.4 * chore(deps): update typescript-eslint monorepo to v3.3.0 * chore(deps): update dependency lint-staged to v10.2.11 * fix(deps): update babel monorepo * fix(deps): update dependency chalk to ^4.1.0 * fix(deps): update dependency execa to ^4.0.2 * fix(deps): update dependency ignore to ^5.1.8 * fix(deps): update dependency typescript to ^3.9.5 * fix(deps): update dependency js-yaml to ^3.14.0 * chore(deps): update dependency eslint to v7.3.0 * fix(deps): update dependency validator to ^13.1.1 * fix(deps): update dependency uuid to ^8.1.0 * chore(deps): update dependency @types/lodash to v4.14.156 * chore(deps): update typescript-eslint monorepo to v3.4.0 * chore(deps): update dependency eslint to v7.3.1 * fix(deps): update dependency uuid to ^8.2.0 * chore(deps): update dependency @types/validator to v13.1.0 * chore(deps): update dependency @types/lodash to v4.14.157 * chore(deps): update typescript-eslint monorepo to v3.5.0 * fix(deps): update babel monorepo to ^7.10.4 (#235) * fix(deps): update babel monorepo to ^7.10.3 * fix(visitors): fix type guards * chore(examples): update submodules * chore(testing): use .mocharc.js * chore(lint): ignore package.json and package-lock.json * feat(visitors): improve type checking for general-callback functions * chore(testing): fix glob pattern Co-authored-by: Renovate Bot <[email protected]> Co-authored-by: Kosaku Kimura <[email protected]> * chore(deps): remove @types/request (#246) * chore(deps): lock file maintenance (#236) Co-authored-by: Renovate Bot <[email protected]> * chore(deps): update dependency @types/js-yaml to v3.12.5 (#243) * chore(deps): update dependency @types/js-yaml to v3.12.5 * chore(index): add type assertion for ServerlessConfig Co-authored-by: Renovate Bot <[email protected]> Co-authored-by: Kosaku Kimura <[email protected]> Co-authored-by: escapinbot <[email protected]> Co-authored-by: Renovate Bot <[email protected]> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
1 parent c9d1f14 commit 25b86e9

File tree

15 files changed

+729
-942
lines changed

15 files changed

+729
-942
lines changed

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ module.exports = {
1919
tryExtensions: ['.ts', '.js', '.json', '.node'],
2020
},
2121
},
22+
ignorePatterns: ['package.json', 'package-lock.json'],
2223
rules: {
2324
'no-dupe-class-members': 'off',
2425
'no-unused-vars': 'off',

.mocharc.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
process.env.NODE_ENV = 'test';
2+
3+
module.exports = {
4+
require: 'ts-node/register/transpile-only',
5+
extension: ['ts'],
6+
watchExtensions: ['ts'],
7+
spec: ['test/**/*.test.ts'],
8+
};

package-lock.json

Lines changed: 454 additions & 728 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"postbuild": "ncp bin/src bin && rimraf bin/src bin/package.json",
2020
"format": "prettier --write --ignore-path .gitignore \"**/*.{ts,js,json,yaml,yml,md}\"",
2121
"test": "run-p test:*",
22-
"test:coverage": "nyc npx ts-mocha -p ./tsconfig.json 'test/**/*.test.ts'",
22+
"test:coverage": "nyc npx mocha",
2323
"test:lint": "eslint --ignore-path .gitignore --cache .",
2424
"test:prettier-check": "prettier -c --ignore-path .gitignore \"**/*.{ts,js,json,yaml,yml,md}\"",
2525
"test:typecheck": "tsc --noEmit",
@@ -39,70 +39,69 @@
3939
"author": "Kimura, Kosaku <[email protected]>",
4040
"license": "MIT",
4141
"dependencies": {
42-
"@babel/code-frame": "^7.8.3",
43-
"@babel/generator": "^7.9.6",
44-
"@babel/parser": "^7.9.6",
45-
"@babel/template": "^7.8.6",
46-
"@babel/traverse": "^7.9.6",
47-
"@babel/types": "^7.9.6",
42+
"@babel/code-frame": "^7.10.3",
43+
"@babel/generator": "^7.10.3",
44+
"@babel/parser": "^7.10.3",
45+
"@babel/template": "^7.10.3",
46+
"@babel/traverse": "^7.10.3",
47+
"@babel/types": "^7.10.3",
4848
"boxen": "^4.2.0",
49-
"chalk": "^4.0.0",
49+
"chalk": "^4.1.0",
5050
"commander": "^5.1.0",
5151
"cosmiconfig": "^6.0.0",
5252
"deasync": "^0.1.20",
53-
"execa": "^4.0.1",
53+
"execa": "^4.0.2",
5454
"https-proxy-agent": "^5.0.0",
55-
"ignore": "^5.1.4",
56-
"js-yaml": "^3.13.1",
55+
"ignore": "^5.1.8",
56+
"js-yaml": "^3.14.0",
5757
"lodash": "^4.17.15",
5858
"mkdirp": "^1.0.4",
5959
"node-fetch": "^2.6.0",
6060
"openapi-types": "^1.3.5",
6161
"package-json": "^6.5.0",
6262
"rimraf": "^3.0.2",
6363
"swagger-parser": "^9.0.1",
64-
"typescript": "^3.8.3",
65-
"uuid": "^8.0.0",
66-
"validator": "^13.0.0"
64+
"typescript": "^3.9.5",
65+
"uuid": "^8.2.0",
66+
"validator": "^13.1.1"
6767
},
6868
"devDependencies": {
6969
"@istanbuljs/nyc-config-typescript": "1.0.1",
7070
"@types/babel__code-frame": "7.0.1",
7171
"@types/babel__generator": "7.6.1",
7272
"@types/babel__template": "7.0.2",
73-
"@types/babel__traverse": "7.0.11",
73+
"@types/babel__traverse": "7.0.12",
7474
"@types/chai": "4.2.11",
7575
"@types/deasync": "0.1.1",
76-
"@types/eslint": "6.8.1",
76+
"@types/eslint": "7.2.0",
7777
"@types/eslint-plugin-prettier": "3.1.0",
78-
"@types/js-yaml": "3.12.4",
79-
"@types/lodash": "4.14.152",
80-
"@types/mkdirp": "1.0.0",
78+
"@types/js-yaml": "3.12.5",
79+
"@types/lodash": "4.14.157",
80+
"@types/mkdirp": "1.0.1",
8181
"@types/mocha": "7.0.2",
8282
"@types/ncp": "2.0.4",
8383
"@types/node": "13.13.5",
8484
"@types/node-fetch": "2.5.7",
8585
"@types/prettier": "2.0.1",
8686
"@types/rimraf": "3.0.0",
8787
"@types/uuid": "8.0.0",
88-
"@types/validator": "13.0.0",
89-
"@typescript-eslint/eslint-plugin": "3.0.0",
90-
"@typescript-eslint/parser": "3.0.0",
88+
"@types/validator": "13.1.0",
89+
"@typescript-eslint/eslint-plugin": "3.5.0",
90+
"@typescript-eslint/parser": "3.5.0",
9191
"chai": "4.2.0",
92-
"eslint": "7.0.0",
92+
"eslint": "7.3.1",
9393
"eslint-config-prettier": "6.11.0",
9494
"eslint-plugin-node": "11.1.0",
95-
"eslint-plugin-prettier": "3.1.3",
95+
"eslint-plugin-prettier": "3.1.4",
9696
"git-list-updated": "1.2.1",
9797
"husky": "4.2.5",
98-
"lint-staged": "10.2.4",
99-
"mocha": "7.1.2",
98+
"lint-staged": "10.2.11",
99+
"mocha": "8.0.1",
100100
"ncp": "2.0.0",
101101
"npm-run-all": "4.1.5",
102-
"nyc": "15.0.1",
102+
"nyc": "15.1.0",
103103
"prettier": "2.0.5",
104-
"ts-mocha": "7.0.0",
105-
"ts-node": "8.10.1"
104+
"ts-node": "8.10.2"
106105
},
107106
"husky": {
108107
"hooks": {

src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,9 @@ export class Escapin {
238238
private loadServerlessConfig(): void {
239239
const serverlessFile = Path.join(this.basePath, SERVERLESS_YML);
240240
if (fs.existsSync(serverlessFile)) {
241-
this.serverlessConfig = loadYaml(fs.readFileSync(serverlessFile, 'utf8'));
241+
this.serverlessConfig = loadYaml(
242+
fs.readFileSync(serverlessFile, 'utf8'),
243+
) as ServerlessConfig;
242244
} else {
243245
this.serverlessConfig = {};
244246
}

src/visitors/asynchronize/errorFirstCallback.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,15 @@ export function fetchErrorFirstCallback(
4949
if (u.isRestElement(property)) {
5050
continue;
5151
}
52-
args.push(property.key);
52+
const { key } = property;
53+
if (!u.isIdentifier(key)) {
54+
continue;
55+
}
56+
args.push(key);
5357
u.replace(
5458
path.parentPath,
55-
property.key,
56-
u.memberExpression(data, property.key),
59+
key,
60+
u.memberExpression(data, key),
5761
path =>
5862
path.isObjectProperty() ||
5963
path.isMemberExpression() ||
Lines changed: 35 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { last } from 'lodash';
2+
import asynchronize from '.';
23
import { EscapinSyntaxError } from '../../error';
34
import { BaseState } from '../../state';
45
import { getNames } from '../../functionTypes';
5-
import { isAsynchronous, isGeneralCallback } from '../../types';
6+
import { isGeneralCallback } from '../../types';
67
import * as u from '../../util';
78

89
export function fetchGeneralCallback(
@@ -26,108 +27,62 @@ export function fetchGeneralCallback(
2627

2728
const callback = callbackPath.node;
2829
const { callee } = node;
29-
let functionName;
30+
let functionName: string;
3031

31-
if (u.isMemberExpression(callee)) {
32+
if (u.isMemberExpression(callee) && u.isIdentifier(callee.property)) {
3233
functionName = callee.property.name;
3334
} else if (u.isIdentifier(callee)) {
3435
functionName = callee.name;
3536
} else {
3637
throw new EscapinSyntaxError('Invalid callee', path.node, state);
3738
}
39+
40+
callbackPath.traverse(asynchronize, state);
41+
42+
let asyncRequired = false;
43+
callbackPath.traverse({
44+
AwaitExpression(path) {
45+
asyncRequired = true;
46+
path.skip();
47+
},
48+
});
49+
50+
if (!asyncRequired) {
51+
path.skip();
52+
return true;
53+
}
54+
55+
callback.async = true;
56+
3857
switch (functionName) {
3958
case 'map':
40-
callback.async = true;
41-
asynchronized.push(node);
4259
path.replaceWith(
4360
u.awaitExpression(
4461
u.expression('Promise.all($ORG)', {
4562
$ORG: node,
4663
}),
4764
),
4865
);
49-
return true;
66+
break;
5067
case 'forEach':
51-
callback.async = true;
52-
asynchronized.push(node);
53-
return true;
54-
default:
5568
break;
56-
}
57-
const temp = path.scope.generateUidIdentifier('temp');
58-
const data = path.scope.generateUidIdentifier('data');
59-
const done = path.scope.generateUidIdentifier('done');
60-
callbackPath.traverse({
61-
VariableDeclaration(path) {
62-
const declarations = path.get('declarations');
63-
const init = declarations[0].get('init');
64-
if (init.isCallExpression()) {
65-
const names = getNames(init.get('callee') as u.NodePath);
66-
const entry = state.escapin.types.get(...names);
67-
if (!isAsynchronous(entry)) {
68-
return;
69-
}
70-
} else if (
71-
!u.isAwaitExpression(init.node) ||
72-
!u.isNewPromise(init.node.argument)
73-
) {
74-
return;
75-
}
76-
const func = u.isAwaitExpression(init.node)
77-
? init.node.argument
78-
: init.node;
79-
if (func === null) {
80-
return;
81-
}
82-
declarations[0].node.init = u.expression(
83-
`(() => { let $TEMP; let $DONE = false;
84-
$FUNC.then($DATA => { $TEMP = $DATA; $DONE = true; });
85-
deasync.loopWhile(_ => !$DONE); return $TEMP; })()`,
86-
{
87-
$DATA: data,
88-
$DONE: done,
89-
$FUNC: func,
90-
$TEMP: temp,
91-
},
92-
);
93-
state.addDependency('deasync');
94-
path.skip();
95-
},
96-
ExpressionStatement(path) {
97-
const { expression } = path.node;
98-
const expressionPath = path.get('expression');
99-
if (expressionPath.isCallExpression()) {
100-
const callExpression = expressionPath as u.NodePath<u.CallExpression>;
101-
const names = getNames(callExpression.get('callee'));
102-
const entry = state.escapin.types.get(...names);
103-
if (!isAsynchronous(entry)) {
104-
return;
105-
}
106-
} else if (
107-
!u.isAwaitExpression(expression) ||
108-
!u.isNewPromise(expression.argument)
109-
) {
110-
return;
111-
}
112-
const func = u.isAwaitExpression(expression)
113-
? expression.argument
114-
: expression;
115-
path.replaceWithMultiple(
116-
u.statements(
117-
`let $DONE = false;
118-
$FUNC.then(_ => { $DONE = true; });
119-
deasync.loopWhile(_ => !$DONE)`,
69+
default:
70+
callbackPath.replaceWith(
71+
u.expression(
72+
`() => { let $TEMP; let $DONE = false;
73+
($FUNC)().then($DATA => { $TEMP = $DATA; $DONE = true; });
74+
deasync.loopWhile(_ => !$DONE); return $TEMP; }`,
12075
{
121-
$DONE: done,
122-
$FUNC: func,
76+
$DATA: path.scope.generateUidIdentifier('data'),
77+
$DONE: path.scope.generateUidIdentifier('done'),
78+
$FUNC: callback,
79+
$TEMP: path.scope.generateUidIdentifier('temp'),
12380
},
12481
),
12582
);
126-
state.unshiftProgramBody(u.snippetFor('misc.import.deasync'));
12783
state.addDependency('deasync');
128-
path.skip();
129-
},
130-
});
84+
break;
85+
}
13186
path.skip();
13287
return true;
13388
}

0 commit comments

Comments
 (0)