1// Copyright 2020 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package misc
6
7import (
8	"strings"
9	"testing"
10
11	. "golang.org/x/tools/internal/lsp/regtest"
12
13	"golang.org/x/tools/internal/lsp/tests"
14)
15
16const unformattedProgram = `
17-- main.go --
18package main
19import "fmt"
20func main(  ) {
21	fmt.Println("Hello World.")
22}
23-- main.go.golden --
24package main
25
26import "fmt"
27
28func main() {
29	fmt.Println("Hello World.")
30}
31`
32
33func TestFormatting(t *testing.T) {
34	Run(t, unformattedProgram, func(t *testing.T, env *Env) {
35		env.OpenFile("main.go")
36		env.FormatBuffer("main.go")
37		got := env.Editor.BufferText("main.go")
38		want := env.ReadWorkspaceFile("main.go.golden")
39		if got != want {
40			t.Errorf("unexpected formatting result:\n%s", tests.Diff(t, want, got))
41		}
42	})
43}
44
45// Tests golang/go#36824.
46func TestFormattingOneLine36824(t *testing.T) {
47	const onelineProgram = `
48-- a.go --
49package main; func f() {}
50
51-- a.go.formatted --
52package main
53
54func f() {}
55`
56	Run(t, onelineProgram, func(t *testing.T, env *Env) {
57		env.OpenFile("a.go")
58		env.FormatBuffer("a.go")
59		got := env.Editor.BufferText("a.go")
60		want := env.ReadWorkspaceFile("a.go.formatted")
61		if got != want {
62			t.Errorf("unexpected formatting result:\n%s", tests.Diff(t, want, got))
63		}
64	})
65}
66
67// Tests golang/go#36824.
68func TestFormattingOneLineImports36824(t *testing.T) {
69	const onelineProgramA = `
70-- a.go --
71package x; func f() {fmt.Println()}
72
73-- a.go.imported --
74package x
75
76import "fmt"
77
78func f() { fmt.Println() }
79`
80	Run(t, onelineProgramA, func(t *testing.T, env *Env) {
81		env.OpenFile("a.go")
82		env.OrganizeImports("a.go")
83		got := env.Editor.BufferText("a.go")
84		want := env.ReadWorkspaceFile("a.go.imported")
85		if got != want {
86			t.Errorf("unexpected formatting result:\n%s", tests.Diff(t, want, got))
87		}
88	})
89}
90
91func TestFormattingOneLineRmImports36824(t *testing.T) {
92	const onelineProgramB = `
93-- a.go --
94package x; import "os"; func f() {}
95
96-- a.go.imported --
97package x
98
99func f() {}
100`
101	Run(t, onelineProgramB, func(t *testing.T, env *Env) {
102		env.OpenFile("a.go")
103		env.OrganizeImports("a.go")
104		got := env.Editor.BufferText("a.go")
105		want := env.ReadWorkspaceFile("a.go.imported")
106		if got != want {
107			t.Errorf("unexpected formatting result:\n%s", tests.Diff(t, want, got))
108		}
109	})
110}
111
112const disorganizedProgram = `
113-- main.go --
114package main
115
116import (
117	"fmt"
118	"errors"
119)
120func main(  ) {
121	fmt.Println(errors.New("bad"))
122}
123-- main.go.organized --
124package main
125
126import (
127	"errors"
128	"fmt"
129)
130func main(  ) {
131	fmt.Println(errors.New("bad"))
132}
133-- main.go.formatted --
134package main
135
136import (
137	"errors"
138	"fmt"
139)
140
141func main() {
142	fmt.Println(errors.New("bad"))
143}
144`
145
146func TestOrganizeImports(t *testing.T) {
147	Run(t, disorganizedProgram, func(t *testing.T, env *Env) {
148		env.OpenFile("main.go")
149		env.OrganizeImports("main.go")
150		got := env.Editor.BufferText("main.go")
151		want := env.ReadWorkspaceFile("main.go.organized")
152		if got != want {
153			t.Errorf("unexpected formatting result:\n%s", tests.Diff(t, want, got))
154		}
155	})
156}
157
158func TestFormattingOnSave(t *testing.T) {
159	Run(t, disorganizedProgram, func(t *testing.T, env *Env) {
160		env.OpenFile("main.go")
161		env.SaveBuffer("main.go")
162		got := env.Editor.BufferText("main.go")
163		want := env.ReadWorkspaceFile("main.go.formatted")
164		if got != want {
165			t.Errorf("unexpected formatting result:\n%s", tests.Diff(t, want, got))
166		}
167	})
168}
169
170// Tests various possibilities for comments in files with CRLF line endings.
171// Import organization in these files has historically been a source of bugs.
172func TestCRLFLineEndings(t *testing.T) {
173	for _, tt := range []struct {
174		issue, want string
175	}{
176		{
177			issue: "41057",
178			want: `package main
179
180/*
181Hi description
182*/
183func Hi() {
184}
185`,
186		},
187		{
188			issue: "42646",
189			want: `package main
190
191import (
192	"fmt"
193)
194
195/*
196func upload(c echo.Context) error {
197	if err := r.ParseForm(); err != nil {
198		fmt.Fprintf(w, "ParseForm() err: %v", err)
199		return
200	}
201	fmt.Fprintf(w, "POST request successful")
202	path_ver := r.FormValue("path_ver")
203	ukclin_ver := r.FormValue("ukclin_ver")
204
205	fmt.Fprintf(w, "Name = %s\n", path_ver)
206	fmt.Fprintf(w, "Address = %s\n", ukclin_ver)
207}
208*/
209
210func main() {
211	const server_port = 8080
212	fmt.Printf("port: %d\n", server_port)
213}
214`,
215		},
216		{
217			issue: "42923",
218			want: `package main
219
220// Line 1.
221// aa
222type Tree struct {
223	arr []string
224}
225`,
226		},
227	} {
228		t.Run(tt.issue, func(t *testing.T) {
229			Run(t, "-- main.go --", func(t *testing.T, env *Env) {
230				crlf := strings.ReplaceAll(tt.want, "\n", "\r\n")
231				env.CreateBuffer("main.go", crlf)
232				env.Await(env.DoneWithOpen())
233				env.OrganizeImports("main.go")
234				got := env.Editor.BufferText("main.go")
235				got = strings.ReplaceAll(got, "\r\n", "\n") // convert everything to LF for simplicity
236				if tt.want != got {
237					t.Errorf("unexpected content after save:\n%s", tests.Diff(t, tt.want, got))
238				}
239			})
240		})
241	}
242}
243