Skip to content

Commit c899865

Browse files
committed
visitor: add delete-unreachable-code and delete-nested-blocks
Signed-off-by: echo094 <20028238+echo094@users.noreply.github.com>
1 parent 1b58b32 commit c899865

File tree

3 files changed

+87
-2
lines changed

3 files changed

+87
-2
lines changed

src/plugin/common.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ module.exports = function (code) {
1010
console.error(`Cannot parse code: ${e.reasonCode}`)
1111
return null
1212
}
13-
const deleteExtra = require('../visitor/delete-extra')
14-
traverse(ast, deleteExtra)
13+
const deleteUnreachableCode = require('../visitor/delete-unreachable-code')
14+
traverse(ast, deleteUnreachableCode)
15+
const deleteNestedBlocks = require('../visitor/delete-nested-blocks')
16+
traverse(ast, deleteNestedBlocks)
1517
const calculateConstantExp = require('../visitor/calculate-constant-exp')
1618
traverse(ast, calculateConstantExp)
1719
const calculateRString = require('../visitor/calculate-rstring')
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
const isIntersect = (path, bindings) => {
2+
path.scope.crawl()
3+
for (const key of Object.keys(bindings)) {
4+
if (path.scope.hasBinding(key)) {
5+
return true
6+
}
7+
}
8+
return false
9+
}
10+
11+
/**
12+
* Avoid nested blocks.
13+
*
14+
* This is slightly different from the @putout/plugin-remove-nested-blocks :
15+
* https://github.com/coderaiser/putout/issues/224#issuecomment-2614051528
16+
*/
17+
module.exports = {
18+
BlockStatement: (path) => {
19+
const { parentPath } = path
20+
if (!parentPath.isBlockStatement() && !parentPath.isProgram()) {
21+
return
22+
}
23+
let valid = path.container.length === 1
24+
if (!isIntersect(parentPath, path.scope.bindings)) {
25+
valid = true
26+
}
27+
if (!valid) {
28+
return
29+
}
30+
path.replaceWithMultiple(path.node.body)
31+
path.scope.crawl()
32+
},
33+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
const t = require('@babel/types')
2+
3+
/**
4+
* DFS the BlockStatement to find and return the location of the first
5+
* ReturnStatement, which is not inside a Conditional Block.
6+
*/
7+
const checkReturnLocation = (body) => {
8+
for (let i = 0; i < body.length; ++i) {
9+
if (t.isReturnStatement(body[i])) {
10+
return i
11+
}
12+
if (t.isBlockStatement(body[i])) {
13+
const ret = checkReturnLocation(body[i].body)
14+
if (~ret) {
15+
return i
16+
}
17+
}
18+
}
19+
return -1
20+
}
21+
22+
/**
23+
* Remove the codes after the first ReturnStatement, which is not inside a
24+
* Conditional Block. The FunctionDeclaration will be preserved.
25+
*
26+
* This is slightly different from the @putout/plugin-remove-unreachable-code :
27+
* https://github.com/coderaiser/putout/issues/224#issuecomment-2614051528
28+
*/
29+
module.exports = {
30+
BlockStatement: (path) => {
31+
const body = path.node.body
32+
const loc = checkReturnLocation(body)
33+
if (loc == -1) {
34+
return
35+
}
36+
for (let i = body.length - 1; i > loc; --i) {
37+
if (t.isFunctionDeclaration(body[i])) {
38+
continue
39+
}
40+
body.splice(i, 1)
41+
}
42+
if (loc === 0 && t.isBlockStatement(body[0])) {
43+
const inner = body.shift()
44+
while (inner.body.length) {
45+
body.unshift(inner.body.pop())
46+
}
47+
}
48+
path.scope.crawl()
49+
},
50+
}

0 commit comments

Comments
 (0)