// Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package diff import ( "fmt" "strings" "golang.org/x/tools/internal/lsp/diff/myers" "golang.org/x/tools/internal/span" ) func init() { ComputeEdits = myersComputeEdits ApplyEdits = myersApplyEdits ToUnified = myersToUnified } func myersComputeEdits(uri span.URI, before, after string) []TextEdit { u := myers.SplitLines(before) f := myers.SplitLines(after) return myersDiffToEdits(uri, myers.Operations(u, f)) } func myersApplyEdits(before string, edits []TextEdit) string { ops := myersEditsToDiff(edits) return strings.Join(myers.ApplyEdits(myers.SplitLines(before), ops), "") } func myersToUnified(from, to string, before string, edits []TextEdit) string { u := myers.SplitLines(before) ops := myersEditsToDiff(edits) return fmt.Sprint(myers.ToUnified(from, to, u, ops)) } func myersDiffToEdits(uri span.URI, ops []*myers.Op) []TextEdit { edits := make([]TextEdit, 0, len(ops)) for _, op := range ops { s := span.New(uri, span.NewPoint(op.I1+1, 1, 0), span.NewPoint(op.I2+1, 1, 0)) switch op.Kind { case myers.Delete: // Delete: unformatted[i1:i2] is deleted. edits = append(edits, TextEdit{Span: s}) case myers.Insert: // Insert: formatted[j1:j2] is inserted at unformatted[i1:i1]. if content := strings.Join(op.Content, ""); content != "" { edits = append(edits, TextEdit{Span: s, NewText: content}) } } } return edits } func myersEditsToDiff(edits []TextEdit) []*myers.Op { iToJ := 0 ops := make([]*myers.Op, len(edits)) for i, edit := range edits { i1 := edit.Span.Start().Line() - 1 i2 := edit.Span.End().Line() - 1 kind := myers.Insert if edit.NewText == "" { kind = myers.Delete } ops[i] = &myers.Op{ Kind: kind, Content: myers.SplitLines(edit.NewText), I1: i1, I2: i2, J1: i1 + iToJ, } if kind == myers.Insert { iToJ += len(ops[i].Content) } else { iToJ -= i2 - i1 } } return ops }