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