Format on save issue
lukehaas opened this issue · 0 comments
lukehaas commented
The following code, when formatted on save will cause duplicate lines to be inserted:
Before:
let arr = [1,2,3];
arr.indexOf(1)
let cplxArr = [
{id: 1},
{id: 2},
{id: 3}
];
cplxArr.findIndex(el => el.id === 1);
after:
let arr = [1, 2, 3];
arr.indexOf(1);
arr.indexOf(1)
let cplxArr = [{ id: 1 }, { id: 2 }, { id: 3 }];
let cplxArr = [
cplxArr.findIndex((el) => el.id === 1);
This is possibly due to the diffing code here:
ICEcoder/assets/js/icecoder.js
Lines 2180 to 2227 in 51cf24b
editorText = difflib.stringAsLines(this.getThisCM().getValue()); | |
prettierText = difflib.stringAsLines(prettierVersion.formatted); | |
// Create a SequenceMatcher instance that diffs the two sets of lines | |
sm = new difflib.SequenceMatcher(editorText, prettierText); | |
// Get the opcodes from the SequenceMatcher instance | |
// Opcodes is a list of 3-tuples describing what changes should be made to the base text in order to yield the new text | |
opcodes = sm.get_opcodes(); | |
docShift = 0; | |
for (let i = 0; i < opcodes.length; i++) { | |
// opcode events may be: | |
// equal = do nothing for this range | |
// replace = replace [1]-[2] with [3]-[4] | |
// insert = replace [1]-[2] with [3]-[4] | |
// delete = replace [1]-[2] with [3]-[4] | |
// Params to determine if we need to set 1 or 0 shift the start line and end line | |
startShift = "delete" === opcodes[i][0] && editorText.length === opcodes[i][2] ? 1 : 0; | |
endShift = "replace" === opcodes[i][0] ? 1 : 0; | |
if ("equal" !== opcodes[i][0]) { | |
// Replace or insert | |
if ("replace" === opcodes[i][0] || "insert" === opcodes[i][0]) { | |
newContent = ""; | |
// For each of the replace/insert lines in Prettier's version | |
for (let j = opcodes[i][3]; j < opcodes[i][4]; j++) { | |
// Build up newContent lines and end with a new line char if not the last line in the range | |
newContent += prettierText[j]; | |
if (j < opcodes[i][4] - 1) { | |
newContent += "\n"; | |
} | |
} | |
} | |
// Delete | |
if ("delete" === opcodes[i][0]) { | |
// Not the last line in doc, the newContent is the line after the section we're deleting in editors version | |
// Else if it's the last line in doc, the content after the section we're deleting is nothing | |
newContent = editorText.length > opcodes[i][2] | |
? editorText[opcodes[i][2]] | |
: ""; | |
} | |
// Replace the range with newContent. The range start line and end line adjust according to | |
// startShift and endShift 1/0 values plus also the +/- docShift which is how much the | |
// editor document has shifted so far during replace ranges | |
this.getThisCM().replaceRange(newContent, {line: opcodes[i][1] - docShift - startShift, ch: 0}, {line: opcodes[i][2] - docShift - endShift, ch: 1000000}, "+input"); | |
// Work out the +/- document shift based on difference between the editors last line in | |
// this diff range and Prettiers last line in this diff range | |
docShift = opcodes[i][2] - opcodes[i][4]; |