| 127 | |
| 128 | // TODO: If we don't have high confidence, return undefined to fall back to slower methods |
| 129 | export async function deterministicApplyLazyEdit({ |
| 130 | oldFile, |
| 131 | newLazyFile, |
| 132 | filename, |
| 133 | /** |
| 134 | * Using this as a flag to slowly reintroduce lazy applies. |
| 135 | * With this set, we will only attempt to deterministically apply |
| 136 | * when there are no lazy blocks and then just replace the whole file, |
| 137 | * and otherwise never use instant apply |
| 138 | */ |
| 139 | onlyFullFileRewrite = false, |
| 140 | }: { |
| 141 | oldFile: string; |
| 142 | newLazyFile: string; |
| 143 | filename: string; |
| 144 | onlyFullFileRewrite?: boolean; |
| 145 | }): Promise<DiffLine[] | undefined> { |
| 146 | const parser = await getParserForFile(filename); |
| 147 | if (!parser) { |
| 148 | return undefined; |
| 149 | } |
| 150 | |
| 151 | const oldTree = parser.parse(oldFile); |
| 152 | let newTree = parser.parse(newLazyFile); |
| 153 | let reconstructedNewFile: string | undefined = undefined; |
| 154 | |
| 155 | if (onlyFullFileRewrite) { |
| 156 | if (!isLazyText(newTree.rootNode.text)) { |
| 157 | const diff = myersDiff(oldFile, newLazyFile); |
| 158 | |
| 159 | if (shouldRejectDiff(diff)) { |
| 160 | return undefined; |
| 161 | } |
| 162 | |
| 163 | return diff; |
| 164 | } else { |
| 165 | return undefined; |
| 166 | } |
| 167 | } |
| 168 | |
| 169 | // If there is no lazy block anywhere, we add our own to the outsides |
| 170 | // so that large chunks of the file don't get removed |
| 171 | if (!findInAst(newTree.rootNode, isLazyBlock)) { |
| 172 | // First, we need to check whether there are matching (similar) nodes at the root level |
| 173 | const firstSimilarNode = findInAst(oldTree.rootNode, (node) => |
| 174 | nodesAreSimilar(node, newTree.rootNode.children[0]), |
| 175 | ); |
| 176 | if (firstSimilarNode?.parent?.equals(oldTree.rootNode)) { |
| 177 | // If so, we tack lazy blocks to start and end, and run the usual algorithm |
| 178 | const result = nodeSurroundedInLazyBlocks(parser, newLazyFile, filename); |
| 179 | if (result) { |
| 180 | newLazyFile = result.newFile; |
| 181 | newTree = result.newTree; |
| 182 | } |
| 183 | } else { |
| 184 | // If not, we need to recursively search for the nodes that are being rewritten, |
| 185 | // and we apply a slightly different algorithm |
| 186 | const newCodeNumLines = newTree.rootNode.text.split("\n").length; |