Skip to content

Commit

Permalink
Fix corrupted diffs in formatting responses (#876)
Browse files Browse the repository at this point in the history
* add failing tests

* internal/hcl: fix insertion interpretation in diff
  • Loading branch information
radeksimko authored Apr 14, 2022
1 parent 57ae373 commit 535c288
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 3 deletions.
12 changes: 9 additions & 3 deletions internal/hcl/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,15 @@ func diffLines(filename string, beforeLines, afterLines source.Lines) document.C

for _, group := range m.GetGroupedOpCodes(context) {
for _, c := range group {
beforeStart, beforeEnd := c.I1, c.I2
afterStart, afterEnd := c.J1, c.J2

if c.Tag == OpEqual {
continue
}

// lines to pick from the original document (to delete/replace/insert to)
beforeStart, beforeEnd := c.I1, c.I2
// lines to pick from the new document (to replace ^ with)
afterStart, afterEnd := c.J1, c.J2

if c.Tag == OpReplace {
var rng *hcl.Range
var newBytes []byte
Expand Down Expand Up @@ -121,6 +123,10 @@ func diffLines(filename string, beforeLines, afterLines source.Lines) document.C
if beforeStart == beforeEnd {
line := beforeLines[beforeStart]
insertRng = line.Range.Ptr()

// We're inserting to the beginning of the line
// which we represent as 0-length range in HCL
insertRng.End = insertRng.Start
} else {
for i, line := range beforeLines[beforeStart:beforeEnd] {
if i == 0 {
Expand Down
37 changes: 37 additions & 0 deletions internal/hcl/diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,43 @@ ccc`,
},
},
},
{
name: "insertion to existing line",
beforeCfg: `resource "aws_lambda_function" "f" {
environment {
variables = {
a = "b"
}
}
}
`,
afterCfg: `resource "aws_lambda_function" "f" {
environment {
variables = {
a = "b"
}
}
}
`,
expectedChanges: document.Changes{
&fileChange{
newText: " environment {\n variables = {\n a = \"b\"\n",
rng: &hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{Line: 2, Column: 1, Byte: 37},
End: hcl.Pos{Line: 6, Column: 1, Byte: 107},
},
},
&fileChange{
newText: " }\n",
rng: &hcl.Range{
Filename: "test.tf",
Start: hcl.Pos{Line: 7, Column: 1, Byte: 113},
End: hcl.Pos{Line: 7, Column: 1, Byte: 113},
},
},
},
},
{
"empty to newline",
``,
Expand Down
123 changes: 123 additions & 0 deletions internal/langserver/handlers/formatting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,3 +277,126 @@ func TestLangServer_formatting_variables(t *testing.T) {
]
}`)
}

func TestLangServer_formatting_diffBug(t *testing.T) {
tmpDir := TempDir(t)

cfg := `resource "aws_lambda_function" "f" {
environment {
variables = {
a = "b"
}
}
}
`
formattedCfg := `resource "aws_lambda_function" "f" {
environment {
variables = {
a = "b"
}
}
}
`

ls := langserver.NewLangServerMock(t, NewMockSession(&MockSessionInput{
TerraformCalls: &exec.TerraformMockCalls{
PerWorkDir: map[string][]*mock.Call{
tmpDir.Path(): {
{
Method: "Version",
Repeatability: 1,
Arguments: []interface{}{
mock.AnythingOfType(""),
},
ReturnArguments: []interface{}{
version.Must(version.NewVersion("0.12.0")),
nil,
nil,
},
},
{
Method: "GetExecPath",
Repeatability: 1,
ReturnArguments: []interface{}{
"",
},
},
{
Method: "Format",
Repeatability: 1,
Arguments: []interface{}{
mock.AnythingOfType("*context.valueCtx"),
[]byte(cfg),
},
ReturnArguments: []interface{}{
[]byte(formattedCfg),
nil,
},
},
},
},
},
}))
stop := ls.Start(t)
defer stop()

ls.Call(t, &langserver.CallRequest{
Method: "initialize",
ReqParams: fmt.Sprintf(`{
"capabilities": {},
"rootUri": %q,
"processId": 12345
}`, tmpDir.URI)})
ls.Notify(t, &langserver.CallRequest{
Method: "initialized",
ReqParams: "{}",
})
ls.Call(t, &langserver.CallRequest{
Method: "textDocument/didOpen",
ReqParams: fmt.Sprintf(`{
"textDocument": {
"version": 0,
"languageId": "terraform",
"text": `+fmt.Sprintf("%q", cfg)+`,
"uri": "%s/main.tf"
}
}`, tmpDir.URI)})
ls.CallAndExpectResponse(t, &langserver.CallRequest{
Method: "textDocument/formatting",
ReqParams: fmt.Sprintf(`{
"textDocument": {
"uri": "%s/main.tf"
}
}`, tmpDir.URI)}, `{
"jsonrpc": "2.0",
"id": 3,
"result": [
{
"range": {
"start": {
"line": 1,
"character": 0
},
"end": {
"line": 5,
"character": 0
}
},
"newText": " environment {\n variables = {\n a = \"b\"\n"
},
{
"range": {
"start": {
"line": 6,
"character": 0
},
"end": {
"line": 6,
"character": 0
}
},
"newText":" }\n"
}
]
}`)
}

0 comments on commit 535c288

Please sign in to comment.