* Recursively removes descendant subtrees of the given AST node and replaces * them with simplified variants to produce simplified source which is still "bad". * Committed modifications are recorded in modifications; the AST is also * mutated so that traversal state stays consistent wi
(node)
| 131 | * @returns {void} |
| 132 | */ |
| 133 | function pruneIrrelevantSubtrees(node) { |
| 134 | for (const key of visitorKeys[node.type] ?? []) { |
| 135 | if (Array.isArray(node[key])) { |
| 136 | for (let index = node[key].length - 1; index >= 0; index--) { |
| 137 | const childNode = node[key][index]; |
| 138 | |
| 139 | if (!childNode) { |
| 140 | continue; |
| 141 | } |
| 142 | |
| 143 | const mod = { |
| 144 | start: childNode.range[0], |
| 145 | end: childNode.range[1], |
| 146 | replacement: "", |
| 147 | }; |
| 148 | |
| 149 | if (reproducesBadCase(buildSource(mod))) { |
| 150 | modifications.push(mod); |
| 151 | node[key].splice(index, 1); |
| 152 | } else { |
| 153 | pruneIrrelevantSubtrees(childNode); |
| 154 | } |
| 155 | } |
| 156 | } else if (typeof node[key] === "object" && node[key] !== null) { |
| 157 | const childNode = node[key]; |
| 158 | |
| 159 | if (isMaybeExpression(childNode)) { |
| 160 | const name = generateNewIdentifierName(); |
| 161 | const mod = { |
| 162 | start: childNode.range[0], |
| 163 | end: childNode.range[1], |
| 164 | replacement: name, |
| 165 | }; |
| 166 | |
| 167 | if (reproducesBadCase(buildSource(mod))) { |
| 168 | modifications.push(mod); |
| 169 | node[key] = { |
| 170 | type: "Identifier", |
| 171 | name, |
| 172 | range: childNode.range, |
| 173 | }; |
| 174 | } else { |
| 175 | pruneIrrelevantSubtrees(childNode); |
| 176 | } |
| 177 | } else if (isStatement(childNode)) { |
| 178 | const mod = { |
| 179 | start: childNode.range[0], |
| 180 | end: childNode.range[1], |
| 181 | replacement: ";", |
| 182 | }; |
| 183 | |
| 184 | if (reproducesBadCase(buildSource(mod))) { |
| 185 | modifications.push(mod); |
| 186 | node[key] = { |
| 187 | type: "EmptyStatement", |
| 188 | range: childNode.range, |
| 189 | }; |
| 190 | } else { |
no test coverage detected
searching dependent graphs…