( programNode: Parser.SyntaxNode, otherNode: Parser.SyntaxNode, )
| 252 | } |
| 253 | |
| 254 | function programNodeIsSimilar( |
| 255 | programNode: Parser.SyntaxNode, |
| 256 | otherNode: Parser.SyntaxNode, |
| 257 | ): boolean { |
| 258 | // Check purely based on whether they are similar strings |
| 259 | const newLines = programNode.text.split("\n"); |
| 260 | const oldLines = otherNode.text.split("\n"); |
| 261 | |
| 262 | // Check that there is a line that matches the start of the old range |
| 263 | const oldFirstLine = oldLines[0].trim(); |
| 264 | let matchForOldFirstLine = -1; |
| 265 | for (let i = 0; i < newLines.length; i++) { |
| 266 | if (newLines[i].trim() === oldFirstLine) { |
| 267 | matchForOldFirstLine = i; |
| 268 | break; |
| 269 | } |
| 270 | } |
| 271 | |
| 272 | if (matchForOldFirstLine < 0) { |
| 273 | return false; |
| 274 | } |
| 275 | |
| 276 | // Check that the last lines match each other |
| 277 | const oldLastLine = oldLines[oldLines.length - 1].trim(); |
| 278 | const newLastLine = newLines[newLines.length - 1].trim(); |
| 279 | if (oldLastLine !== newLastLine) { |
| 280 | return false; |
| 281 | } |
| 282 | |
| 283 | // Check that the number of matching lines is at least half of the shorter length |
| 284 | let matchingLines = 0; |
| 285 | for (let i = 0; i < Math.min(newLines.length, oldLines.length); i++) { |
| 286 | if (oldLines[i].trim() === newLines[matchForOldFirstLine + i].trim()) { |
| 287 | matchingLines += 1; |
| 288 | } |
| 289 | } |
| 290 | |
| 291 | if (matchingLines >= Math.max(newLines.length, oldLines.length) / 2) { |
| 292 | return true; |
| 293 | } |
| 294 | |
| 295 | return false; |
| 296 | } |
| 297 | |
| 298 | /** |
| 299 | * Determine whether two nodes are similar |
no outgoing calls
no test coverage detected