icecoder/ICEcoder

Format on save issue

lukehaas opened this issue · 0 comments

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];