Why setFormula breaks what you expect
The first time I hit this, I spent twenty minutes debugging why every cell in column C had the same output. The culprit: Range.setFormula() stamps one literal A1 string into every cell in the range. If you pass '=A2*B2', every row gets exactly =A2*B2, not =A3*B3, not =A4*B4. There is no shifting. It behaves like Ctrl+V paste, not drag-fill.
setFormulaR1C1() is the fix. R1C1 notation describes references relative to the cell being written. RC[-2] means 'same row, two columns to the left.' When Apps Script writes that into C2, it resolves as A2; into C3, it resolves as A3. The formula text you pass is identical for every row; the engine handles the per-row translation at write time.