GoPLS Viewer

Home|gopls/internal/imports/fix_test.go
1// Copyright 2013 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 imports
6
7import (
8    "context"
9    "flag"
10    "fmt"
11    "go/build"
12    "io/ioutil"
13    "log"
14    "path/filepath"
15    "reflect"
16    "sort"
17    "strings"
18    "sync"
19    "testing"
20
21    "golang.org/x/tools/go/packages/packagestest"
22    "golang.org/x/tools/internal/gocommand"
23)
24
25var testDebug = flag.Bool("debug"false"enable debug output")
26
27var tests = []struct {
28    name       string
29    formatOnly bool
30    inout    string
31}{
32    // Adding an import to an existing parenthesized import
33    {
34        name"factored_imports_add",
35        in`package foo
36import (
37  "fmt"
38)
39func bar() {
40var b bytes.Buffer
41fmt.Println(b.String())
42}
43`,
44        out`package foo
45
46import (
47    "bytes"
48    "fmt"
49)
50
51func bar() {
52    var b bytes.Buffer
53    fmt.Println(b.String())
54}
55`,
56    },
57
58    // Adding an import to an existing parenthesized import,
59    // verifying it goes into the first section.
60    {
61        name"factored_imports_add_first_sec",
62        in`package foo
63import (
64  "fmt"
65
66  "github.com/golang/snappy"
67)
68func bar() {
69var b bytes.Buffer
70_ = snappy.ErrCorrupt
71fmt.Println(b.String())
72}
73`,
74        out`package foo
75
76import (
77    "bytes"
78    "fmt"
79
80    "github.com/golang/snappy"
81)
82
83func bar() {
84    var b bytes.Buffer
85    _ = snappy.ErrCorrupt
86    fmt.Println(b.String())
87}
88`,
89    },
90
91    // Adding an import to an existing parenthesized import,
92    // verifying it goes into the first section. (test 2)
93    {
94        name"factored_imports_add_first_sec_2",
95        in`package foo
96import (
97  "fmt"
98
99  "github.com/golang/snappy"
100)
101func bar() {
102_ = math.NaN
103_ = fmt.Sprintf
104_ = snappy.ErrCorrupt
105}
106`,
107        out`package foo
108
109import (
110    "fmt"
111    "math"
112
113    "github.com/golang/snappy"
114)
115
116func bar() {
117    _ = math.NaN
118    _ = fmt.Sprintf
119    _ = snappy.ErrCorrupt
120}
121`,
122    },
123
124    // Adding a new import line, without parens
125    {
126        name"add_import_section",
127        in`package foo
128func bar() {
129var b bytes.Buffer
130}
131`,
132        out`package foo
133
134import "bytes"
135
136func bar() {
137    var b bytes.Buffer
138}
139`,
140    },
141
142    // Adding two new imports, which should make a parenthesized import decl.
143    {
144        name"add_import_paren_section",
145        in`package foo
146func bar() {
147_, _ := bytes.Buffer, zip.NewReader
148}
149`,
150        out`package foo
151
152import (
153    "archive/zip"
154    "bytes"
155)
156
157func bar() {
158    _, _ := bytes.Buffer, zip.NewReader
159}
160`,
161    },
162
163    // Make sure we don't add things twice
164    {
165        name"no_double_add",
166        in`package foo
167func bar() {
168_, _ := bytes.Buffer, bytes.NewReader
169}
170`,
171        out`package foo
172
173import "bytes"
174
175func bar() {
176    _, _ := bytes.Buffer, bytes.NewReader
177}
178`,
179    },
180
181    // Make sure we don't add packages that don't have the right exports
182    {
183        name"no_mismatched_add",
184        in`package foo
185
186func bar() {
187    _ := bytes.NonexistentSymbol
188}
189`,
190        out`package foo
191
192func bar() {
193    _ := bytes.NonexistentSymbol
194}
195`,
196    },
197
198    // Remove unused imports, 1 of a factored block
199    {
200        name"remove_unused_1_of_2",
201        in`package foo
202import (
203"bytes"
204"fmt"
205)
206
207func bar() {
208_, _ := bytes.Buffer, bytes.NewReader
209}
210`,
211        out`package foo
212
213import (
214    "bytes"
215)
216
217func bar() {
218    _, _ := bytes.Buffer, bytes.NewReader
219}
220`,
221    },
222
223    // Remove unused imports, 2 of 2
224    {
225        name"remove_unused_2_of_2",
226        in`package foo
227import (
228"bytes"
229"fmt"
230)
231
232func bar() {
233}
234`,
235        out`package foo
236
237func bar() {
238}
239`,
240    },
241
242    // Remove unused imports, 1 of 1
243    {
244        name"remove_unused_1_of_1",
245        in`package foo
246
247import "fmt"
248
249func bar() {
250}
251`,
252        out`package foo
253
254func bar() {
255}
256`,
257    },
258
259    // Don't remove empty imports.
260    {
261        name"dont_remove_empty_imports",
262        in`package foo
263import (
264_ "image/png"
265_ "image/jpeg"
266)
267`,
268        out`package foo
269
270import (
271    _ "image/jpeg"
272    _ "image/png"
273)
274`,
275    },
276
277    // Don't remove dot imports.
278    {
279        name"dont_remove_dot_imports",
280        in`package foo
281import (
282. "foo"
283. "bar"
284)
285`,
286        out`package foo
287
288import (
289    . "bar"
290    . "foo"
291)
292`,
293    },
294
295    // Skip refs the parser can resolve.
296    {
297        name"skip_resolved_refs",
298        in`package foo
299
300func f() {
301    type t struct{ Println func(string) }
302    fmt := t{Println: func(string) {}}
303    fmt.Println("foo")
304}
305`,
306        out`package foo
307
308func f() {
309    type t struct{ Println func(string) }
310    fmt := t{Println: func(string) {}}
311    fmt.Println("foo")
312}
313`,
314    },
315
316    // Do not add a package we already have a resolution for.
317    {
318        name"skip_template",
319        in`package foo
320
321import "html/template"
322
323func f() { t = template.New("sometemplate") }
324`,
325        out`package foo
326
327import "html/template"
328
329func f() { t = template.New("sometemplate") }
330`,
331    },
332
333    // Don't touch cgo
334    {
335        name"cgo",
336        in`package foo
337
338/*
339#include <foo.h>
340*/
341import "C"
342`,
343        out`package foo
344
345/*
346#include <foo.h>
347*/
348import "C"
349`,
350    },
351
352    // Put some things in their own section
353    {
354        name"make_sections",
355        in`package foo
356
357import (
358"os"
359)
360
361func foo () {
362_, _ = os.Args, fmt.Println
363_, _ = snappy.ErrCorrupt, p.P
364}
365`,
366        out`package foo
367
368import (
369    "fmt"
370    "os"
371
372    "github.com/golang/snappy"
373    "rsc.io/p"
374)
375
376func foo() {
377    _, _ = os.Args, fmt.Println
378    _, _ = snappy.ErrCorrupt, p.P
379}
380`,
381    },
382    // Merge import blocks, even when no additions are required.
383    {
384        name"merge_import_blocks_no_fix",
385        in`package foo
386
387import (
388    "fmt"
389)
390import "os"
391
392import (
393    "rsc.io/p"
394)
395
396var _, _ = os.Args, fmt.Println
397var _, _ = snappy.ErrCorrupt, p.P
398`,
399        out`package foo
400
401import (
402    "fmt"
403    "os"
404
405    "github.com/golang/snappy"
406    "rsc.io/p"
407)
408
409var _, _ = os.Args, fmt.Println
410var _, _ = snappy.ErrCorrupt, p.P
411`,
412    },
413    // Delete existing empty import block
414    {
415        name"delete_empty_import_block",
416        in`package foo
417
418import ()
419`,
420        out`package foo
421`,
422    },
423
424    // Use existing empty import block
425    {
426        name"use_empty_import_block",
427        in`package foo
428
429import ()
430
431func f() {
432    _ = fmt.Println
433}
434`,
435        out`package foo
436
437import "fmt"
438
439func f() {
440    _ = fmt.Println
441}
442`,
443    },
444
445    // Blank line before adding new section.
446    {
447        name"blank_line_before_new_group",
448        in`package foo
449
450import (
451    "fmt"
452    "net"
453)
454
455func f() {
456    _ = net.Dial
457    _ = fmt.Printf
458    _ = snappy.ErrCorrupt
459}
460`,
461        out`package foo
462
463import (
464    "fmt"
465    "net"
466
467    "github.com/golang/snappy"
468)
469
470func f() {
471    _ = net.Dial
472    _ = fmt.Printf
473    _ = snappy.ErrCorrupt
474}
475`,
476    },
477
478    // Blank line between standard library and third-party stuff.
479    {
480        name"blank_line_separating_std_and_third_party",
481        in`package foo
482
483import (
484    "github.com/golang/snappy"
485    "fmt"
486    "net"
487)
488
489func f() {
490    _ = net.Dial
491    _ = fmt.Printf
492    _ = snappy.Foo
493}
494`,
495        out`package foo
496
497import (
498    "fmt"
499    "net"
500
501    "github.com/golang/snappy"
502)
503
504func f() {
505    _ = net.Dial
506    _ = fmt.Printf
507    _ = snappy.Foo
508}
509`,
510    },
511
512    // golang.org/issue/6884
513    {
514        name"new_imports_before_comment",
515        in`package main
516
517// A comment
518func main() {
519    fmt.Println("Hello, world")
520}
521`,
522        out`package main
523
524import "fmt"
525
526// A comment
527func main() {
528    fmt.Println("Hello, world")
529}
530`,
531    },
532
533    // golang.org/issue/7132
534    {
535        name"new_section_for_dotless_import",
536        in`package main
537
538import (
539"fmt"
540
541"gu"
542"manypackages.com/packagea"
543)
544
545var (
546a = packagea.A
547b = gu.A
548c = fmt.Printf
549)
550`,
551        out`package main
552
553import (
554    "fmt"
555
556    "gu"
557
558    "manypackages.com/packagea"
559)
560
561var (
562    a = packagea.A
563    b = gu.A
564    c = fmt.Printf
565)
566`,
567    },
568
569    {
570        name"fragment_with_main",
571        in:   `func main(){fmt.Println("Hello, world")}`,
572        out`package main
573
574import "fmt"
575
576func main() { fmt.Println("Hello, world") }
577`,
578    },
579
580    {
581        name"fragment_without_main",
582        in:   `func notmain(){fmt.Println("Hello, world")}`,
583        out`import "fmt"
584
585func notmain() { fmt.Println("Hello, world") }`,
586    },
587
588    // Remove first import within in a 2nd/3rd/4th/etc. section.
589    // golang.org/issue/7679
590    {
591        name"remove_first_import_in_section",
592        in`package main
593
594import (
595    "fmt"
596
597    "manypackages.com/packagea"
598    "manypackages.com/packageb"
599)
600
601func main() {
602    var _ = fmt.Println
603    //var _ = packagea.A
604    var _ = packageb.B
605}
606`,
607        out`package main
608
609import (
610    "fmt"
611
612    "manypackages.com/packageb"
613)
614
615func main() {
616    var _ = fmt.Println
617    //var _ = packagea.A
618    var _ = packageb.B
619}
620`,
621    },
622
623    // Blank line can be added before all types of import declarations.
624    // golang.org/issue/7866
625    {
626        name"new_section_for_all_kinds_of_imports",
627        in`package main
628
629import (
630    "fmt"
631    renamed_packagea "manypackages.com/packagea"
632
633    . "manypackages.com/packageb"
634    "io"
635
636    _ "manypackages.com/packagec"
637    "strings"
638)
639
640var _, _, _, _, _ = fmt.Errorf, io.Copy, strings.Contains, renamed_packagea.A, B
641`,
642        out`package main
643
644import (
645    "fmt"
646
647    renamed_packagea "manypackages.com/packagea"
648
649    "io"
650
651    . "manypackages.com/packageb"
652
653    "strings"
654
655    _ "manypackages.com/packagec"
656)
657
658var _, _, _, _, _ = fmt.Errorf, io.Copy, strings.Contains, renamed_packagea.A, B
659`,
660    },
661
662    // Blank line can be added even when first import of group has comment with quote
663    {
664        name"new_section_where_trailing_comment_has_quote",
665        in`package main
666
667import (
668    "context"
669    bar "local.com/bar"
670    baz "local.com/baz"
671    buzz "local.com/buzz"
672    "github.com/golang/snappy" // this is a "typical" import
673)
674
675var _, _, _, _, _ = context.Background, bar.B, baz.B, buzz.B, snappy.ErrCorrupt
676`,
677        out`package main
678
679import (
680    "context"
681
682    "github.com/golang/snappy" // this is a "typical" import
683
684    bar "local.com/bar"
685    baz "local.com/baz"
686    buzz "local.com/buzz"
687)
688
689var _, _, _, _, _ = context.Background, bar.B, baz.B, buzz.B, snappy.ErrCorrupt
690`,
691    },
692
693    // Non-idempotent comment formatting
694    // golang.org/issue/8035
695    {
696        name"comments_formatted",
697        in`package main
698
699import (
700    "fmt"                     // A
701    "go/ast"                  // B
702    _ "manypackages.com/packagec"    // C
703)
704
705func main() { _, _ = fmt.Print, ast.Walk }
706`,
707        out`package main
708
709import (
710    "fmt"    // A
711    "go/ast" // B
712
713    _ "manypackages.com/packagec" // C
714)
715
716func main() { _, _ = fmt.Print, ast.Walk }
717`,
718    },
719
720    // Failure to delete all duplicate imports
721    // golang.org/issue/8459
722    {
723        name"remove_duplicates",
724        in`package main
725
726import (
727    "fmt"
728    "log"
729    "log"
730    "math"
731)
732
733func main() { fmt.Println("pi:", math.Pi) }
734`,
735        out`package main
736
737import (
738    "fmt"
739    "math"
740)
741
742func main() { fmt.Println("pi:", math.Pi) }
743`,
744    },
745
746    // Too aggressive prefix matching
747    // golang.org/issue/9961
748    {
749        name"no_extra_groups",
750        in`package p
751
752import (
753    "zip"
754
755    "rsc.io/p"
756)
757
758var (
759    _ = fmt.Print
760    _ = zip.Store
761    _ p.P
762    _ = regexp.Compile
763)
764`,
765        out`package p
766
767import (
768    "fmt"
769    "regexp"
770    "zip"
771
772    "rsc.io/p"
773)
774
775var (
776    _ = fmt.Print
777    _ = zip.Store
778    _ p.P
779    _ = regexp.Compile
780)
781`,
782    },
783
784    // Unused named import is mistaken for unnamed import
785    // golang.org/issue/8149
786    {
787        name"named_import_doesnt_provide_package_name",
788        in`package main
789
790import foo "fmt"
791
792func main() { fmt.Println() }
793`,
794        out`package main
795
796import "fmt"
797
798func main() { fmt.Println() }
799`,
800    },
801
802    // Unused named import is mistaken for unnamed import
803    // golang.org/issue/8149
804    {
805        name"unused_named_import_removed",
806        in`package main
807
808import (
809    "fmt"
810    x "fmt"
811)
812
813func main() { fmt.Println() }
814`,
815        out`package main
816
817import (
818    "fmt"
819)
820
821func main() { fmt.Println() }
822`,
823    },
824
825    {
826        name"ignore_unexported_identifier",
827        in`package main
828var _ = fmt.unexported`,
829        out`package main
830
831var _ = fmt.unexported
832`,
833    },
834
835    // FormatOnly
836    {
837        name:       "formatonly_works",
838        formatOnlytrue,
839        in`package main
840
841import (
842"fmt"
843"manypackages.com/packagea"
844)
845
846func main() {}
847`,
848        out`package main
849
850import (
851    "fmt"
852
853    "manypackages.com/packagea"
854)
855
856func main() {}
857`,
858    },
859
860    {
861        name"preserve_import_group",
862        in`package p
863
864import (
865    "bytes"
866    "fmt"
867)
868
869var _ = fmt.Sprintf
870`,
871        out`package p
872
873import (
874    "fmt"
875)
876
877var _ = fmt.Sprintf
878`,
879    },
880    {
881        name"import_grouping_not_path_dependent_no_groups",
882        in`package main
883
884import (
885    "time"
886)
887
888func main() {
889    _ = snappy.ErrCorrupt
890    _ = p.P
891    _ = time.Parse
892}
893`,
894        out`package main
895
896import (
897    "time"
898
899    "github.com/golang/snappy"
900    "rsc.io/p"
901)
902
903func main() {
904    _ = snappy.ErrCorrupt
905    _ = p.P
906    _ = time.Parse
907}
908`,
909    },
910
911    {
912        name"import_grouping_not_path_dependent_existing_group",
913        in`package main
914
915import (
916    "time"
917
918    "github.com/golang/snappy"
919)
920
921func main() {
922    _ = snappy.ErrCorrupt
923    _ = p.P
924    _ = time.Parse
925}
926`,
927        out`package main
928
929import (
930    "time"
931
932    "github.com/golang/snappy"
933    "rsc.io/p"
934)
935
936func main() {
937    _ = snappy.ErrCorrupt
938    _ = p.P
939    _ = time.Parse
940}
941`,
942    },
943
944    // golang.org/issue/12097
945    {
946        name"package_statement_insertion_preserves_comments",
947        in`// a
948// b
949// c
950
951func main() {
952    _ = fmt.Println
953}`,
954        out`package main
955
956import "fmt"
957
958// a
959// b
960// c
961
962func main() {
963    _ = fmt.Println
964}
965`,
966    },
967
968    {
969        name"import_comment_stays_on_import",
970        in`package main
971
972import (
973    "math" // fun
974)
975
976func main() {
977    x := math.MaxInt64
978    fmt.Println(strings.Join(",", []string{"hi"}), x)
979}`,
980        out`package main
981
982import (
983    "fmt"
984    "math" // fun
985    "strings"
986)
987
988func main() {
989    x := math.MaxInt64
990    fmt.Println(strings.Join(",", []string{"hi"}), x)
991}
992`,
993    },
994
995    {
996        name"no_blank_after_comment",
997        in`package main
998
999import (
1000    _ "io"
1001    _ "net/http"
1002    _ "net/http/pprof" // install the pprof http handlers
1003    _ "strings"
1004)
1005
1006func main() {
1007}
1008`,
1009        out`package main
1010
1011import (
1012    _ "io"
1013    _ "net/http"
1014    _ "net/http/pprof" // install the pprof http handlers
1015    _ "strings"
1016)
1017
1018func main() {
1019}
1020`,
1021    },
1022
1023    {
1024        name"no_blank_after_comment_reordered",
1025        in`package main
1026
1027import (
1028    _ "io"
1029    _ "net/http/pprof" // install the pprof http handlers
1030    _ "net/http"
1031    _ "strings"
1032)
1033
1034func main() {
1035}
1036`,
1037        out`package main
1038
1039import (
1040    _ "io"
1041    _ "net/http"
1042    _ "net/http/pprof" // install the pprof http handlers
1043    _ "strings"
1044)
1045
1046func main() {
1047}
1048`,
1049    },
1050
1051    {
1052        name"no_blank_after_comment_unnamed",
1053        in`package main
1054
1055import (
1056    "encoding/json"
1057    "io"
1058    "net/http"
1059    _ "net/http/pprof" // install the pprof http handlers
1060    "strings"
1061
1062    "manypackages.com/packagea"
1063)
1064
1065func main() {
1066    _ = strings.ToUpper("hello")
1067    _ = io.EOF
1068    var (
1069        _ json.Number
1070        _ *http.Request
1071        _ packagea.A
1072    )
1073}
1074`,
1075        out`package main
1076
1077import (
1078    "encoding/json"
1079    "io"
1080    "net/http"
1081    _ "net/http/pprof" // install the pprof http handlers
1082    "strings"
1083
1084    "manypackages.com/packagea"
1085)
1086
1087func main() {
1088    _ = strings.ToUpper("hello")
1089    _ = io.EOF
1090    var (
1091        _ json.Number
1092        _ *http.Request
1093        _ packagea.A
1094    )
1095}
1096`,
1097    },
1098
1099    {
1100        name"blank_after_package_statement_with_comment",
1101        in`package p // comment
1102
1103import "math"
1104
1105var _ = fmt.Printf
1106`,
1107        out`package p // comment
1108
1109import "fmt"
1110
1111var _ = fmt.Printf
1112`,
1113    },
1114
1115    {
1116        name"blank_after_package_statement_no_comment",
1117        in`package p
1118
1119import "math"
1120
1121var _ = fmt.Printf
1122`,
1123        out`package p
1124
1125import "fmt"
1126
1127var _ = fmt.Printf
1128`,
1129    },
1130
1131    {
1132        name"cryptorand_preferred_easy_possible",
1133        in`package p
1134
1135var _ = rand.Read
1136`,
1137        out`package p
1138
1139import "crypto/rand"
1140
1141var _ = rand.Read
1142`,
1143    },
1144
1145    {
1146        name"cryptorand_preferred_easy_impossible",
1147        in`package p
1148
1149var _ = rand.NewZipf
1150`,
1151        out`package p
1152
1153import "math/rand"
1154
1155var _ = rand.NewZipf
1156`,
1157    },
1158
1159    {
1160        name"cryptorand_preferred_complex_possible",
1161        in`package p
1162
1163var _, _ = rand.Read, rand.Prime
1164`,
1165        out`package p
1166
1167import "crypto/rand"
1168
1169var _, _ = rand.Read, rand.Prime
1170`,
1171    },
1172
1173    {
1174        name"cryptorand_preferred_complex_impossible",
1175        in`package p
1176
1177var _, _ = rand.Read, rand.NewZipf
1178`,
1179        out`package p
1180
1181import "math/rand"
1182
1183var _, _ = rand.Read, rand.NewZipf
1184`,
1185    },
1186}
1187
1188func TestSimpleCases(t *testing.T) {
1189    const localPrefix = "local.com,github.com/local"
1190    for _tt := range tests {
1191        t.Run(tt.name, func(t *testing.T) {
1192            testConfig{
1193                modules: []packagestest.Module{
1194                    {
1195                        Name:  "golang.org/fake",
1196                        Filesfm{"x.go"tt.in},
1197                    },
1198                    // Skeleton non-stdlib packages for use during testing.
1199                    // Each includes one arbitrary symbol, e.g. the first declaration in the first file.
1200                    // Try not to add more without a good reason.
1201                    // DO NOT USE PACKAGES NOT LISTED HERE -- they will be downloaded!
1202                    {
1203                        Name:  "rsc.io",
1204                        Filesfm{"p/x.go""package p\nfunc P(){}\n"},
1205                    },
1206                    {
1207                        Name:  "github.com/golang/snappy",
1208                        Filesfm{"x.go""package snappy\nvar ErrCorrupt error\n"},
1209                    },
1210                    {
1211                        Name"manypackages.com",
1212                        Filesfm{
1213                            "packagea/x.go""package packagea\nfunc A(){}\n",
1214                            "packageb/x.go""package packageb\nfunc B(){}\n",
1215                            "packagec/x.go""package packagec\nfunc C(){}\n",
1216                            "packaged/x.go""package packaged\nfunc D(){}\n",
1217                        },
1218                    },
1219                    {
1220                        Name:  "local.com",
1221                        Filesfm{"foo/x.go""package foo\nfunc Foo(){}\n"},
1222                    },
1223                    {
1224                        Name:  "github.com/local",
1225                        Filesfm{"bar/x.go""package bar\nfunc Bar(){}\n"},
1226                    },
1227                },
1228            }.test(t, func(t *goimportTest) {
1229                options := &Options{
1230                    LocalPrefixlocalPrefix,
1231                    TabWidth:    8,
1232                    TabIndent:   true,
1233                    Comments:    true,
1234                    Fragment:    true,
1235                    FormatOnly:  tt.formatOnly,
1236                }
1237                t.assertProcessEquals("golang.org/fake""x.go"niloptionstt.out)
1238            })
1239
1240        })
1241    }
1242}
1243
1244func TestAppengine(t *testing.T) {
1245    const input = `package p
1246
1247var _, _, _ = fmt.Printf, appengine.Main, datastore.ErrInvalidEntityType
1248`
1249
1250    const want = `package p
1251
1252import (
1253    "fmt"
1254
1255    "appengine"
1256    "appengine/datastore"
1257)
1258
1259var _, _, _ = fmt.Printf, appengine.Main, datastore.ErrInvalidEntityType
1260`
1261
1262    testConfig{
1263        gopathOnlytrue// can't create a module named appengine, so no module tests.
1264        modules: []packagestest.Module{
1265            {
1266                Name:  "golang.org/fake",
1267                Filesfm{"x.go"input},
1268            },
1269            {
1270                Name"appengine",
1271                Filesfm{
1272                    "x.go":           "package appengine\nfunc Main(){}\n",
1273                    "datastore/x.go""package datastore\nvar ErrInvalidEntityType error\n",
1274                },
1275            },
1276        },
1277    }.processTest(t"golang.org/fake""x.go"nilnilwant)
1278}
1279
1280func TestReadFromFilesystem(t *testing.T) {
1281    tests := []struct {
1282        name    string
1283        inout string
1284    }{
1285        {
1286            name"works",
1287            in`package foo
1288func bar() {
1289fmt.Println("hi")
1290}
1291`,
1292            out`package foo
1293
1294import "fmt"
1295
1296func bar() {
1297    fmt.Println("hi")
1298}
1299`,
1300        },
1301        {
1302            name"missing_package",
1303            in`
1304func bar() {
1305fmt.Println("hi")
1306}
1307`,
1308            out`
1309import "fmt"
1310
1311func bar() {
1312    fmt.Println("hi")
1313}
1314`,
1315        },
1316    }
1317
1318    for _tt := range tests {
1319        t.Run(tt.name, func(t *testing.T) {
1320            options := &Options{
1321                TabWidth:  8,
1322                TabIndenttrue,
1323                Comments:  true,
1324                Fragment:  true,
1325            }
1326            testConfig{
1327                modulepackagestest.Module{
1328                    Name:  "golang.org/fake",
1329                    Filesfm{"x.go"tt.in},
1330                },
1331            }.processTest(t"golang.org/fake""x.go"niloptionstt.out)
1332        })
1333    }
1334
1335}
1336
1337// Test support for packages in GOPATH that are actually symlinks.
1338// Also test that a symlink loop does not block the process.
1339func TestImportSymlinks(t *testing.T) {
1340    const input = `package p
1341
1342var (
1343    _ = fmt.Print
1344    _ = mypkg.Foo
1345)
1346`
1347    const want = `package p
1348
1349import (
1350    "fmt"
1351
1352    "golang.org/fake/x/y/mypkg"
1353)
1354
1355var (
1356    _ = fmt.Print
1357    _ = mypkg.Foo
1358)
1359`
1360
1361    testConfig{
1362        modulepackagestest.Module{
1363            Name"golang.org/fake",
1364            Filesfm{
1365                "target/f.go":                "package mypkg\nvar Foo = 123\n",
1366                "x/y/mypkg":                  packagestest.Symlink("../../target"), // valid symlink
1367                "x/y/apkg":                   packagestest.Symlink(".."),           // symlink loop
1368                "myotherpackage/toformat.go"input,
1369            },
1370        },
1371    }.processTest(t"golang.org/fake""myotherpackage/toformat.go"nilnilwant)
1372}
1373
1374func TestImportSymlinksWithIgnore(t *testing.T) {
1375    const input = `package p
1376
1377var (
1378    _ = fmt.Print
1379    _ = mypkg.Foo
1380)
1381`
1382    const want = `package p
1383
1384import "fmt"
1385
1386var (
1387    _ = fmt.Print
1388    _ = mypkg.Foo
1389)
1390`
1391
1392    testConfig{
1393        gopathOnlytrue,
1394        modulepackagestest.Module{
1395            Name"golang.org/fake",
1396            Filesfm{
1397                "target/f.go":            "package mypkg\nvar Foo = 123\n",
1398                "x/y/mypkg":              packagestest.Symlink("../../target"), // valid symlink
1399                "x/y/apkg":               packagestest.Symlink(".."),           // symlink loop
1400                "myotherpkg/toformat.go"input,
1401                "../../.goimportsignore""golang.org/fake/x/y/mypkg\n",
1402            },
1403        },
1404    }.processTest(t"golang.org/fake""myotherpkg/toformat.go"nilnilwant)
1405}
1406
1407// Test for x/y/v2 convention for package y.
1408func TestModuleVersion(t *testing.T) {
1409    const input = `package p
1410
1411import (
1412    "fmt"
1413
1414    "github.com/foo/v2"
1415)
1416
1417var (
1418    _ = fmt.Print
1419    _ = foo.Foo
1420)
1421`
1422
1423    testConfig{
1424        modules: []packagestest.Module{
1425            {
1426                Name:  "mypkg.com/outpkg",
1427                Filesfm{"toformat.go"input},
1428            },
1429            {
1430                Name:  "github.com/foo/v2",
1431                Filesfm{"x.go""package foo\n func Foo(){}\n"},
1432            },
1433        },
1434    }.processTest(t"mypkg.com/outpkg""toformat.go"nilnilinput)
1435}
1436
1437// Test for correctly identifying the name of a vendored package when it
1438// differs from its directory name. In this test, the import line
1439// "mypkg.com/mypkg_v1" would be removed if goimports wasn't able to detect
1440// that the package name is "mypkg".
1441func TestVendorPackage(t *testing.T) {
1442    const input = `package p
1443import (
1444    "fmt"
1445    "mypkg.com/mypkg_v1"
1446)
1447var _, _ = fmt.Print, mypkg.Foo
1448`
1449
1450    const want = `package p
1451
1452import (
1453    "fmt"
1454
1455    mypkg "mypkg.com/mypkg_v1"
1456)
1457
1458var _, _ = fmt.Print, mypkg.Foo
1459`
1460
1461    testConfig{
1462        gopathOnlytrue,
1463        modulepackagestest.Module{
1464            Name"mypkg.com/outpkg",
1465            Filesfm{
1466                "vendor/mypkg.com/mypkg_v1/f.go""package mypkg\nvar Foo = 123\n",
1467                "toformat.go":                    input,
1468            },
1469        },
1470    }.processTest(t"mypkg.com/outpkg""toformat.go"nilnilwant)
1471}
1472
1473func TestInternal(t *testing.T) {
1474    const input = `package bar
1475
1476var _ = race.Acquire
1477`
1478    const importAdded = `package bar
1479
1480import "foo.com/internal/race"
1481
1482var _ = race.Acquire
1483`
1484
1485    // Packages under the same directory should be able to use internal packages.
1486    testConfig{
1487        modulepackagestest.Module{
1488            Name"foo.com",
1489            Filesfm{
1490                "internal/race/x.go""package race\n func Acquire(){}\n",
1491                "bar/x.go":           input,
1492            },
1493        },
1494    }.processTest(t"foo.com""bar/x.go"nilnilimportAdded)
1495
1496    // Packages outside the same directory should not.
1497    testConfig{
1498        modules: []packagestest.Module{
1499            {
1500                Name:  "foo.com",
1501                Filesfm{"internal/race/x.go""package race\n func Acquire(){}\n"},
1502            },
1503            {
1504                Name:  "bar.com",
1505                Filesfm{"x.go"input},
1506            },
1507        },
1508    }.processTest(t"bar.com""x.go"nilnilinput)
1509}
1510
1511func TestProcessVendor(t *testing.T) {
1512    const input = `package p
1513
1514var _ = hpack.HuffmanDecode
1515`
1516    const want = `package p
1517
1518import "golang.org/x/net/http2/hpack"
1519
1520var _ = hpack.HuffmanDecode
1521`
1522    testConfig{
1523        gopathOnlytrue,
1524        modulepackagestest.Module{
1525            Name"foo.com",
1526            Filesfm{
1527                "vendor/golang.org/x/net/http2/hpack/huffman.go""package hpack\nfunc HuffmanDecode() { }\n",
1528                "bar/x.go"input,
1529            },
1530        },
1531    }.processTest(t"foo.com""bar/x.go"nilnilwant)
1532}
1533
1534func TestFindStdlib(t *testing.T) {
1535    tests := []struct {
1536        pkg     string
1537        symbols []string
1538        want    string
1539    }{
1540        {"http", []string{"Get"}, "net/http"},
1541        {"http", []string{"Get""Post"}, "net/http"},
1542        {"http", []string{"Get""Foo"}, ""},
1543        {"bytes", []string{"Buffer"}, "bytes"},
1544        {"ioutil", []string{"Discard"}, "io/ioutil"},
1545    }
1546    for _tt := range tests {
1547        input := "package p\n"
1548        for _sym := range tt.symbols {
1549            input += fmt.Sprintf("var _ = %s.%s\n"tt.pkgsym)
1550        }
1551        testConfig{
1552            modulepackagestest.Module{
1553                Name:  "foo.com",
1554                Filesfm{"x.go"input},
1555            },
1556        }.test(t, func(t *goimportTest) {
1557            buferr := t.process("foo.com""x.go"nilnil)
1558            if err != nil {
1559                t.Fatal(err)
1560            }
1561            if got := string(buf); !strings.Contains(gottt.want) {
1562                t.Errorf("Process(%q) = %q, wanted it to contain %q"inputbuftt.want)
1563            }
1564        })
1565    }
1566}
1567
1568// https://golang.org/issue/31814
1569func TestStdlibNotPrefixed(t *testing.T) {
1570    const input = `package p
1571var _ = bytes.Buffer
1572`
1573    const want = `package p
1574
1575import "bytes"
1576
1577var _ = bytes.Buffer
1578`
1579    // Force a scan of the stdlib.
1580    savedStdlib := stdlib
1581    defer func() { stdlib = savedStdlib }()
1582    stdlib = map[string][]string{}
1583
1584    testConfig{
1585        modulepackagestest.Module{
1586            Name:  "ignored.com",
1587            Filesfm{"x.go""package x"},
1588        },
1589    }.test(t, func(t *goimportTest) {
1590        // Run in GOROOT/src so that the std module shows up in go list -m all.
1591        t.env.WorkingDir = filepath.Join(t.goroot"src")
1592        goterr := t.processNonModule(filepath.Join(t.goroot"src/x.go"), []byte(input), nil)
1593        if err != nil {
1594            t.Fatalf("Process() = %v"err)
1595        }
1596        if string(got) != want {
1597            t.Errorf("Got:\n%s\nWant:\n%s"gotwant)
1598        }
1599    })
1600}
1601
1602func TestStdlibSelfImports(t *testing.T) {
1603    const input = `package ecdsa
1604
1605var _ = ecdsa.GenerateKey
1606`
1607
1608    testConfig{
1609        modulepackagestest.Module{
1610            Name:  "ignored.com",
1611            Filesfm{"x.go""package x"},
1612        },
1613    }.test(t, func(t *goimportTest) {
1614        goterr := t.processNonModule(filepath.Join(t.goroot"src/crypto/ecdsa/foo.go"), []byte(input), nil)
1615        if err != nil {
1616            t.Fatalf("Process() = %v"err)
1617        }
1618        if string(got) != input {
1619            t.Errorf("Got:\n%s\nWant:\n%s"gotinput)
1620        }
1621    })
1622}
1623
1624type testConfig struct {
1625    gopathOnly bool
1626    module     packagestest.Module
1627    modules    []packagestest.Module
1628}
1629
1630// fm is the type for a packagestest.Module's Files, abbreviated for shorter lines.
1631type fm map[string]interface{}
1632
1633func (c testConfigtest(t *testing.Tfn func(*goimportTest)) {
1634    t.Helper()
1635
1636    if c.module.Name != "" {
1637        c.modules = []packagestest.Module{c.module}
1638    }
1639
1640    for _exporter := range packagestest.All {
1641        t.Run(exporter.Name(), func(t *testing.T) {
1642            t.Helper()
1643            if c.gopathOnly && exporter.Name() == "Modules" {
1644                t.Skip("test marked GOPATH-only")
1645            }
1646            exported := packagestest.Export(texporterc.modules)
1647            defer exported.Cleanup()
1648
1649            env := map[string]string{}
1650            for _kv := range exported.Config.Env {
1651                split := strings.SplitN(kv"="2)
1652                env[split[0]] = split[1]
1653            }
1654            it := &goimportTest{
1655                Tt,
1656                env: &ProcessEnv{
1657                    Env:         env,
1658                    WorkingDir:  exported.Config.Dir,
1659                    GocmdRunner: &gocommand.Runner{},
1660                },
1661                exportedexported,
1662            }
1663            if *testDebug {
1664                it.env.Logf = log.Printf
1665            }
1666            // packagestest clears out GOROOT to work around golang/go#32849,
1667            // which isn't relevant here. Fill it back in so we can find the standard library.
1668            it.env.Env["GOROOT"] = build.Default.GOROOT
1669            it.goroot = build.Default.GOROOT
1670
1671            fn(it)
1672        })
1673    }
1674}
1675
1676func (c testConfigprocessTest(t *testing.Tmodulefile stringcontents []byteopts *Optionswant string) {
1677    t.Helper()
1678    c.test(t, func(t *goimportTest) {
1679        t.Helper()
1680        t.assertProcessEquals(modulefilecontentsoptswant)
1681    })
1682}
1683
1684type goimportTest struct {
1685    *testing.T
1686    goroot   string
1687    env      *ProcessEnv
1688    exported *packagestest.Exported
1689}
1690
1691func (t *goimportTestprocess(modulefile stringcontents []byteopts *Options) ([]byteerror) {
1692    t.Helper()
1693    f := t.exported.File(modulefile)
1694    if f == "" {
1695        t.Fatalf("%v not found in exported files (typo in filename?)"file)
1696    }
1697    return t.processNonModule(fcontentsopts)
1698}
1699
1700func (t *goimportTestprocessNonModule(file stringcontents []byteopts *Options) ([]byteerror) {
1701    if contents == nil {
1702        var err error
1703        contentserr = ioutil.ReadFile(file)
1704        if err != nil {
1705            return nilerr
1706        }
1707    }
1708    if opts == nil {
1709        opts = &Options{CommentstrueTabIndenttrueTabWidth8}
1710    }
1711    // ProcessEnv is not safe for concurrent use. Make a copy.
1712    opts.Env = t.env.CopyConfig()
1713    return Process(filecontentsopts)
1714}
1715
1716func (t *goimportTestassertProcessEquals(modulefile stringcontents []byteopts *Optionswant string) {
1717    buferr := t.process(modulefilecontentsopts)
1718    if err != nil {
1719        t.Fatalf("Process() = %v"err)
1720    }
1721    if string(buf) != want {
1722        t.Errorf("Got:\n'%s'\nWant:\n'%s'"bufwant// 's show empty lines
1723    }
1724}
1725
1726// Tests that added imports are renamed when the import path's base doesn't
1727// match its package name.
1728func TestRenameWhenPackageNameMismatch(t *testing.T) {
1729    const input = `package main
1730 const Y = bar.X`
1731
1732    const want = `package main
1733
1734import bar "foo.com/foo/bar/baz"
1735
1736const Y = bar.X
1737`
1738    testConfig{
1739        modulepackagestest.Module{
1740            Name"foo.com",
1741            Filesfm{
1742                "foo/bar/baz/x.go""package bar \n const X = 1",
1743                "test/t.go":        input,
1744            },
1745        },
1746    }.processTest(t"foo.com""test/t.go"nilnilwant)
1747}
1748
1749func TestPanicAstutils(t *testing.T) {
1750    t.Skip("panic in ast/astutil/imports.go, should be PostionFor(,false) at lines 273, 274, at least")
1751    const input = `package main
1752//line mah.go:600
1753
1754import (
1755"foo.com/a.thing"
1756"foo.com/surprise"
1757"foo.com/v1"
1758"foo.com/other/v2"
1759"foo.com/other/v3"
1760)
1761`
1762
1763    const want = `package main
1764
1765//line mah.go:600
1766
1767import (
1768    "foo.com/a.thing"
1769    "foo.com/go-thing"
1770    gow "foo.com/go-wrong"
1771    v2 "foo.com/other/v2"
1772    "foo.com/other/v3"
1773    bar "foo.com/surprise"
1774    v1 "foo.com/v1"
1775)
1776
1777`
1778
1779    testConfig{
1780        modulepackagestest.Module{
1781            Name"foo.com",
1782            Filesfm{
1783                "test/t.go"input,
1784            },
1785        },
1786    }.processTest(t"foo.com""test/t.go"nilnilwant)
1787}
1788
1789// without PositionFor in sortImports this test panics
1790func TestPanic51916(t *testing.T) {
1791    const input = `package main
1792//line mah.go:600
1793
1794import (
1795"foo.com/a.thing"
1796"foo.com/surprise"
1797"foo.com/v1"
1798"foo.com/other/v2"
1799"foo.com/other/v3"
1800"foo.com/go-thing"
1801"foo.com/go-wrong"
1802)
1803
1804var _ = []interface{}{bar.X, v1.Y, a.A, v2.V2, other.V3, thing.Thing, gow.Wrong}`
1805
1806    const want = `package main
1807
1808//line mah.go:600
1809
1810import (
1811    "foo.com/a.thing"
1812    "foo.com/go-thing"
1813    gow "foo.com/go-wrong"
1814    v2 "foo.com/other/v2"
1815    "foo.com/other/v3"
1816    bar "foo.com/surprise"
1817    v1 "foo.com/v1"
1818)
1819
1820var _ = []interface{}{bar.X, v1.Y, a.A, v2.V2, other.V3, thing.Thing, gow.Wrong}
1821`
1822
1823    testConfig{
1824        modulepackagestest.Module{
1825            Name"foo.com",
1826            Filesfm{
1827                "a.thing/a.go":  "package a \n const A = 1",
1828                "surprise/x.go""package bar \n const X = 1",
1829                "v1/x.go":       "package v1 \n const Y = 1",
1830                "other/v2/y.go""package v2 \n const V2 = 1",
1831                "other/v3/z.go""package other \n const V3 = 1",
1832                "go-thing/b.go""package thing \n const Thing = 1",
1833                "go-wrong/b.go""package gow \n const Wrong = 1",
1834                "test/t.go":     input,
1835            },
1836        },
1837    }.processTest(t"foo.com""test/t.go"nilnilwant)
1838}
1839
1840// Tests that an existing import with badly mismatched path/name has its name
1841// correctly added. See #28645 and #29041.
1842// and check that //line directives are ignored (#51916)
1843func TestAddNameToMismatchedImport(t *testing.T) {
1844    const input = `package main
1845
1846import (
1847"foo.com/a.thing"
1848"foo.com/surprise"
1849"foo.com/v1"
1850"foo.com/other/v2"
1851"foo.com/other/v3"
1852"foo.com/go-thing"
1853"foo.com/go-wrong"
1854)
1855
1856var _ = []interface{}{bar.X, v1.Y, a.A, v2.V2, other.V3, thing.Thing, gow.Wrong}`
1857
1858    const want = `package main
1859
1860import (
1861    "foo.com/a.thing"
1862    "foo.com/go-thing"
1863    gow "foo.com/go-wrong"
1864    v2 "foo.com/other/v2"
1865    "foo.com/other/v3"
1866    bar "foo.com/surprise"
1867    v1 "foo.com/v1"
1868)
1869
1870var _ = []interface{}{bar.X, v1.Y, a.A, v2.V2, other.V3, thing.Thing, gow.Wrong}
1871`
1872
1873    testConfig{
1874        modulepackagestest.Module{
1875            Name"foo.com",
1876            Filesfm{
1877                "a.thing/a.go":  "package a \n const A = 1",
1878                "surprise/x.go""package bar \n const X = 1",
1879                "v1/x.go":       "package v1 \n const Y = 1",
1880                "other/v2/y.go""package v2 \n const V2 = 1",
1881                "other/v3/z.go""package other \n const V3 = 1",
1882                "go-thing/b.go""package thing \n const Thing = 1",
1883                "go-wrong/b.go""package gow \n const Wrong = 1",
1884                "test/t.go":     input,
1885            },
1886        },
1887    }.processTest(t"foo.com""test/t.go"nilnilwant)
1888}
1889
1890// Tests that the LocalPrefix option causes imports
1891// to be added into a later group (num=3).
1892func TestLocalPrefix(t *testing.T) {
1893    tests := []struct {
1894        name        string
1895        modules     []packagestest.Module
1896        localPrefix string
1897        src         string
1898        want        string
1899    }{
1900        {
1901            name"one_local",
1902            modules: []packagestest.Module{
1903                {
1904                    Name"foo.com",
1905                    Filesfm{
1906                        "bar/bar.go""package bar \n const X = 1",
1907                    },
1908                },
1909            },
1910            localPrefix"foo.com/",
1911            src:         "package main \n const Y = bar.X \n const _ = runtime.GOOS",
1912            want`package main
1913
1914import (
1915    "runtime"
1916
1917    "foo.com/bar"
1918)
1919
1920const Y = bar.X
1921const _ = runtime.GOOS
1922`,
1923        },
1924        {
1925            name"two_local",
1926            modules: []packagestest.Module{
1927                {
1928                    Name"foo.com",
1929                    Filesfm{
1930                        "foo/foo.go":     "package foo \n const X = 1",
1931                        "foo/bar/bar.go""package bar \n const X = 1",
1932                    },
1933                },
1934            },
1935            localPrefix"foo.com/foo",
1936            src:         "package main \n const Y = bar.X \n const Z = foo.X \n const _ = runtime.GOOS",
1937            want`package main
1938
1939import (
1940    "runtime"
1941
1942    "foo.com/foo"
1943    "foo.com/foo/bar"
1944)
1945
1946const Y = bar.X
1947const Z = foo.X
1948const _ = runtime.GOOS
1949`,
1950        },
1951        {
1952            name"three_prefixes",
1953            modules: []packagestest.Module{
1954                {
1955                    Name:  "example.org/pkg",
1956                    Filesfm{"pkg.go""package pkg \n const A = 1"},
1957                },
1958                {
1959                    Name:  "foo.com",
1960                    Filesfm{"bar/bar.go""package bar \n const B = 1"},
1961                },
1962                {
1963                    Name:  "code.org/r/p",
1964                    Filesfm{"expproj/expproj.go""package expproj \n const C = 1"},
1965                },
1966            },
1967            localPrefix"example.org/pkg,foo.com/,code.org",
1968            src:         "package main \n const X = pkg.A \n const Y = bar.B \n const Z = expproj.C \n const _ = runtime.GOOS",
1969            want`package main
1970
1971import (
1972    "runtime"
1973
1974    "code.org/r/p/expproj"
1975    "example.org/pkg"
1976    "foo.com/bar"
1977)
1978
1979const X = pkg.A
1980const Y = bar.B
1981const Z = expproj.C
1982const _ = runtime.GOOS
1983`,
1984        },
1985    }
1986
1987    for _tt := range tests {
1988        t.Run(tt.name, func(t *testing.T) {
1989            testConfig{
1990                // The module being processed has to be first so it's the primary module.
1991                modulesappend([]packagestest.Module{{
1992                    Name:  "test.com",
1993                    Filesfm{"t.go"tt.src},
1994                }}, tt.modules...),
1995            }.test(t, func(t *goimportTest) {
1996                options := &Options{
1997                    LocalPrefixtt.localPrefix,
1998                    TabWidth:    8,
1999                    TabIndent:   true,
2000                    Comments:    true,
2001                    Fragment:    true,
2002                }
2003                t.assertProcessEquals("test.com""t.go"niloptionstt.want)
2004            })
2005        })
2006    }
2007}
2008
2009// Tests that "package documentation" files are ignored.
2010func TestIgnoreDocumentationPackage(t *testing.T) {
2011    const input = `package x
2012
2013const Y = foo.X
2014`
2015    const want = `package x
2016
2017import "foo.com/foo"
2018
2019const Y = foo.X
2020`
2021
2022    testConfig{
2023        modulepackagestest.Module{
2024            Name"foo.com",
2025            Filesfm{
2026                "foo/foo.go""package foo\nconst X = 1\n",
2027                "foo/doc.go""package documentation \n // just to confuse things\n",
2028                "x/x.go":     input,
2029            },
2030        },
2031    }.processTest(t"foo.com""x/x.go"nilnilwant)
2032}
2033
2034// Tests importPathToNameGoPathParse and in particular that it stops
2035// after finding the first non-documentation package name, not
2036// reporting an error on inconsistent package names (since it should
2037// never make it that far).
2038func TestImportPathToNameGoPathParse(t *testing.T) {
2039    testConfig{
2040        modulepackagestest.Module{
2041            Name"example.net/pkg",
2042            Filesfm{
2043                "doc.go""package documentation\n"// ignored
2044                "gen.go""package main\n",          // also ignored
2045                "pkg.go""package the_pkg_name_to_find\n  and this syntax error is ignored because of parser.PackageClauseOnly",
2046                "z.go":   "package inconsistent\n"// inconsistent but ignored
2047            },
2048        },
2049    }.test(t, func(t *goimportTest) {
2050        if strings.Contains(t.Name(), "GoPackages") {
2051            t.Skip("go/packages does not ignore package main")
2052        }
2053        rerr := t.env.GetResolver()
2054        if err != nil {
2055            t.Fatal(err)
2056        }
2057        srcDir := filepath.Dir(t.exported.File("example.net/pkg""z.go"))
2058        nameserr := r.loadPackageNames([]string{"example.net/pkg"}, srcDir)
2059        if err != nil {
2060            t.Fatal(err)
2061        }
2062        const want = "the_pkg_name_to_find"
2063        if got := names["example.net/pkg"]; got != want {
2064            t.Errorf("loadPackageNames(..) = %q; want %q"gotwant)
2065        }
2066    })
2067}
2068
2069func TestIgnoreConfiguration(t *testing.T) {
2070    const input = `package x
2071
2072const _ = pkg.X
2073`
2074    const want = `package x
2075
2076import "foo.com/otherwise-longer-so-worse-example/foo/pkg"
2077
2078const _ = pkg.X
2079`
2080
2081    testConfig{
2082        gopathOnlytrue,
2083        modulepackagestest.Module{
2084            Name"foo.com",
2085            Filesfm{
2086                "../.goimportsignore":                              "# comment line\n\n foo.com/example"// tests comment, blank line, whitespace trimming
2087                "example/pkg/pkg.go":                               "package pkg\nconst X = 1",
2088                "otherwise-longer-so-worse-example/foo/pkg/pkg.go""package pkg\nconst X = 1",
2089                "x/x.go"input,
2090            },
2091        },
2092    }.processTest(t"foo.com""x/x.go"nilnilwant)
2093}
2094
2095// Skip "node_modules" directory.
2096func TestSkipNodeModules(t *testing.T) {
2097    const input = `package x
2098
2099const _ = pkg.X
2100`
2101    const want = `package x
2102
2103import "foo.com/otherwise-longer/not_modules/pkg"
2104
2105const _ = pkg.X
2106`
2107
2108    testConfig{
2109        gopathOnlytrue,
2110        modulepackagestest.Module{
2111            Name"foo.com",
2112            Filesfm{
2113                "example/node_modules/pkg/a.go":         "package pkg\nconst X = 1",
2114                "otherwise-longer/not_modules/pkg/a.go""package pkg\nconst X = 1",
2115                "x/x.go":                                input,
2116            },
2117        },
2118    }.processTest(t"foo.com""x/x.go"nilnilwant)
2119}
2120
2121// Tests that package global variables with the same name and function name as
2122// a function in a separate package do not result in an import which masks
2123// the global variable
2124func TestGlobalImports(t *testing.T) {
2125    const usesGlobal = `package pkg
2126
2127func doSomething() {
2128    t := time.Now()
2129}
2130`
2131
2132    const declaresGlobal = `package pkg
2133
2134type Time struct{}
2135
2136func (t Time) Now() Time {
2137    return Time{}
2138}
2139
2140var time Time
2141`
2142
2143    testConfig{
2144        modulepackagestest.Module{
2145            Name"foo.com",
2146            Filesfm{
2147                "pkg/uses.go":   usesGlobal,
2148                "pkg/global.go"declaresGlobal,
2149            },
2150        },
2151    }.processTest(t"foo.com""pkg/uses.go"nilnilusesGlobal)
2152}
2153
2154// Some people put multiple packages' files in the same directory. Globals
2155// declared in other packages should be ignored.
2156func TestGlobalImports_DifferentPackage(t *testing.T) {
2157    const declaresGlobal = `package main
2158var fmt int
2159`
2160    const input = `package pkg
2161var _ = fmt.Printf
2162`
2163    const want = `package pkg
2164
2165import "fmt"
2166
2167var _ = fmt.Printf
2168`
2169
2170    testConfig{
2171        modulepackagestest.Module{
2172            Name"foo.com",
2173            Filesfm{
2174                "pkg/main.go"declaresGlobal,
2175                "pkg/uses.go"input,
2176            },
2177        },
2178    }.processTest(t"foo.com""pkg/uses.go"nilnilwant)
2179}
2180
2181func TestGlobalImports_MultipleMains(t *testing.T) {
2182    const declaresGlobal = `package main
2183var fmt int
2184`
2185    const input = `package main
2186import "fmt"
2187var _, _ = fmt.Printf, bytes.Equal
2188`
2189    const want = `package main
2190
2191import (
2192    "bytes"
2193    "fmt"
2194)
2195
2196var _, _ = fmt.Printf, bytes.Equal
2197`
2198
2199    testConfig{
2200        modulepackagestest.Module{
2201            Name"foo.com",
2202            Filesfm{
2203                "pkg/main.go"declaresGlobal,
2204                "pkg/uses.go"input,
2205            },
2206        },
2207    }.processTest(t"foo.com""pkg/uses.go"nilnilwant)
2208}
2209
2210// Tests that sibling files - other files in the same package - can provide an
2211// import that may not be the default one otherwise.
2212func TestSiblingImports(t *testing.T) {
2213
2214    // provide is the sibling file that provides the desired import.
2215    const provide = `package siblingimporttest
2216
2217import "local/log"
2218import "my/bytes"
2219import renamed "fmt"
2220
2221func LogSomething() {
2222    log.Print("Something")
2223    bytes.SomeFunc()
2224    renamed.Println("Something")
2225}
2226`
2227
2228    // need is the file being tested that needs the import.
2229    const need = `package siblingimporttest
2230
2231var _ = bytes.Buffer{}
2232
2233func LogSomethingElse() {
2234    log.Print("Something else")
2235    renamed.Println("Yet another")
2236}
2237`
2238
2239    // want is the expected result file
2240    const want = `package siblingimporttest
2241
2242import (
2243    "bytes"
2244    renamed "fmt"
2245    "local/log"
2246)
2247
2248var _ = bytes.Buffer{}
2249
2250func LogSomethingElse() {
2251    log.Print("Something else")
2252    renamed.Println("Yet another")
2253}
2254`
2255
2256    testConfig{
2257        modulepackagestest.Module{
2258            Name"foo.com",
2259            Filesfm{
2260                "p/needs_import.go":    need,
2261                "p/provides_import.go"provide,
2262            },
2263        },
2264    }.processTest(t"foo.com""p/needs_import.go"nilnilwant)
2265}
2266
2267// Tests #29180: a sibling import of the right package with the wrong name is used.
2268func TestSiblingImport_Misnamed(t *testing.T) {
2269    const sibling = `package main
2270import renamed "fmt"
2271var _ = renamed.Printf
2272`
2273    const input = `package pkg
2274var _ = fmt.Printf
2275`
2276    const want = `package pkg
2277
2278import "fmt"
2279
2280var _ = fmt.Printf
2281`
2282
2283    testConfig{
2284        modulepackagestest.Module{
2285            Name"foo.com",
2286            Filesfm{
2287                "pkg/main.go"sibling,
2288                "pkg/uses.go"input,
2289            },
2290        },
2291    }.processTest(t"foo.com""pkg/uses.go"nilnilwant)
2292
2293}
2294
2295// Tests that an input file's own package is ignored.
2296func TestIgnoreOwnPackage(t *testing.T) {
2297    const input = `package pkg
2298
2299const _ = pkg.X
2300`
2301    const want = `package pkg
2302
2303const _ = pkg.X
2304`
2305
2306    testConfig{
2307        modulepackagestest.Module{
2308            Name"foo.com",
2309            Filesfm{
2310                "pkg/a.go""package pkg\nconst X = 1",
2311                "pkg/b.go"input,
2312            },
2313        },
2314    }.processTest(t"foo.com""pkg/b.go"nilnilwant)
2315}
2316
2317func TestExternalTestImportsPackageUnderTest(t *testing.T) {
2318    const provide = `package pkg
2319func DoIt(){}
2320`
2321    const input = `package pkg_test
2322
2323var _ = pkg.DoIt`
2324
2325    const want = `package pkg_test
2326
2327import "foo.com/pkg"
2328
2329var _ = pkg.DoIt
2330`
2331
2332    testConfig{
2333        modulepackagestest.Module{
2334            Name"foo.com",
2335            Filesfm{
2336                "pkg/provide.go"provide,
2337                "pkg/x_test.go":  input,
2338            },
2339        },
2340    }.processTest(t"foo.com""pkg/x_test.go"nilnilwant)
2341}
2342
2343func TestPkgIsCandidate(t *testing.T) {
2344    tests := []struct {
2345        name     string
2346        filename string
2347        pkgIdent string
2348        pkg      *pkg
2349        want     bool
2350    }{
2351        {
2352            name:     "normal_match",
2353            filename"/gopath/src/my/pkg/pkg.go",
2354            pkgIdent"client",
2355            pkg: &pkg{
2356                dir:             "/gopath/src/client",
2357                importPathShort"client",
2358            },
2359            wanttrue,
2360        },
2361        {
2362            name:     "no_match",
2363            filename"/gopath/src/my/pkg/pkg.go",
2364            pkgIdent"zzz",
2365            pkg: &pkg{
2366                dir:             "/gopath/src/client",
2367                importPathShort"client",
2368            },
2369            wantfalse,
2370        },
2371        {
2372            name:     "match_too_early",
2373            filename"/gopath/src/my/pkg/pkg.go",
2374            pkgIdent"client",
2375            pkg: &pkg{
2376                dir:             "/gopath/src/client/foo/foo/foo",
2377                importPathShort"client/foo/foo",
2378            },
2379            wantfalse,
2380        },
2381        {
2382            name:     "substring_match",
2383            filename"/gopath/src/my/pkg/pkg.go",
2384            pkgIdent"client",
2385            pkg: &pkg{
2386                dir:             "/gopath/src/foo/go-client",
2387                importPathShort"foo/go-client",
2388            },
2389            wanttrue,
2390        },
2391        {
2392            name:     "hidden_internal",
2393            filename"/gopath/src/my/pkg/pkg.go",
2394            pkgIdent"client",
2395            pkg: &pkg{
2396                dir:             "/gopath/src/foo/internal/client",
2397                importPathShort"foo/internal/client",
2398            },
2399            wantfalse,
2400        },
2401        {
2402            name:     "visible_internal",
2403            filename"/gopath/src/foo/bar.go",
2404            pkgIdent"client",
2405            pkg: &pkg{
2406                dir:             "/gopath/src/foo/internal/client",
2407                importPathShort"foo/internal/client",
2408            },
2409            wanttrue,
2410        },
2411        {
2412            name:     "invisible_vendor",
2413            filename"/gopath/src/foo/bar.go",
2414            pkgIdent"client",
2415            pkg: &pkg{
2416                dir:             "/gopath/src/other/vendor/client",
2417                importPathShort"client",
2418            },
2419            wantfalse,
2420        },
2421        {
2422            name:     "visible_vendor",
2423            filename"/gopath/src/foo/bar.go",
2424            pkgIdent"client",
2425            pkg: &pkg{
2426                dir:             "/gopath/src/foo/vendor/client",
2427                importPathShort"client",
2428            },
2429            wanttrue,
2430        },
2431        {
2432            name:     "match_with_hyphens",
2433            filename"/gopath/src/foo/bar.go",
2434            pkgIdent"socketio",
2435            pkg: &pkg{
2436                dir:             "/gopath/src/foo/socket-io",
2437                importPathShort"foo/socket-io",
2438            },
2439            wanttrue,
2440        },
2441        {
2442            name:     "match_with_mixed_case",
2443            filename"/gopath/src/foo/bar.go",
2444            pkgIdent"fooprod",
2445            pkg: &pkg{
2446                dir:             "/gopath/src/foo/FooPROD",
2447                importPathShort"foo/FooPROD",
2448            },
2449            wanttrue,
2450        },
2451        {
2452            name:     "matches_with_hyphen_and_caps",
2453            filename"/gopath/src/foo/bar.go",
2454            pkgIdent"fooprod",
2455            pkg: &pkg{
2456                dir:             "/gopath/src/foo/Foo-PROD",
2457                importPathShort"foo/Foo-PROD",
2458            },
2459            wanttrue,
2460        },
2461    }
2462    for itt := range tests {
2463        t.Run(tt.name, func(t *testing.T) {
2464            refs := references{tt.pkgIdentnil}
2465            got := pkgIsCandidate(tt.filenamerefstt.pkg)
2466            if got != tt.want {
2467                t.Errorf("test %d. pkgIsCandidate(%q, %q, %+v) = %v; want %v",
2468                    itt.filenamett.pkgIdent, *tt.pkggottt.want)
2469            }
2470        })
2471    }
2472}
2473
2474// Issue 20941: this used to panic on Windows.
2475func TestProcessStdin(t *testing.T) {
2476    testConfig{
2477        modulepackagestest.Module{
2478            Name"foo.com",
2479        },
2480    }.test(t, func(t *goimportTest) {
2481        goterr := t.processNonModule("<standard input>", []byte("package main\nfunc main() {\n\tfmt.Println(123)\n}\n"), nil)
2482        if err != nil {
2483            t.Fatal(err)
2484        }
2485        if !strings.Contains(string(got), `"fmt"`) {
2486            t.Errorf("expected fmt import; got: %s"got)
2487        }
2488    })
2489}
2490
2491// Tests LocalPackagePromotion when there is a local package that matches, it
2492// should be the closest match.
2493// https://golang.org/issues/17557
2494func TestLocalPackagePromotion(t *testing.T) {
2495    const input = `package main
2496var c = &config.SystemConfig{}
2497`
2498    const want = `package main
2499
2500import "mycompany.net/tool/config"
2501
2502var c = &config.SystemConfig{}
2503`
2504
2505    testConfig{
2506        modules: []packagestest.Module{
2507            {
2508                Name:  "config.net/config",
2509                Filesfm{"config.go""package config\n type SystemConfig struct {}"}, // Will match but should not be first choice
2510            },
2511            {
2512                Name:  "mycompany.net/config",
2513                Filesfm{"config.go""package config\n type SystemConfig struct {}"}, // Will match but should not be first choice
2514            },
2515            {
2516                Name"mycompany.net/tool",
2517                Filesfm{
2518                    "config/config.go""package config\n type SystemConfig struct {}"// Local package should be promoted over shorter package
2519                    "main.go":          input,
2520                },
2521            },
2522        },
2523    }.processTest(t"mycompany.net/tool""main.go"nilnilwant)
2524}
2525
2526// Tests FindImportInLocalGoFiles looks at the import lines for other Go files in the
2527// local directory, since the user is likely to import the same packages in the current
2528// Go file.  If an import is found that satisfies the need, it should be used over the
2529// standard library.
2530// https://golang.org/issues/17557
2531func TestFindImportInLocalGoFiles(t *testing.T) {
2532    const input = `package main
2533 var _ = &bytes.Buffer{}`
2534
2535    const want = `package main
2536
2537import "bytes.net/bytes"
2538
2539var _ = &bytes.Buffer{}
2540`
2541    testConfig{
2542        modules: []packagestest.Module{
2543            {
2544                Name"mycompany.net/tool",
2545                Filesfm{
2546                    "io.go":   "package main\n import \"bytes.net/bytes\"\n var _ = &bytes.Buffer{}"// Contains package import that will cause stdlib to be ignored
2547                    "main.go"input,
2548                },
2549            },
2550            {
2551                Name:  "bytes.net/bytes",
2552                Filesfm{"bytes.go""package bytes\n type Buffer struct {}"}, // Should be selected over standard library
2553            },
2554        },
2555    }.processTest(t"mycompany.net/tool""main.go"nilnilwant)
2556}
2557
2558func TestInMemoryFile(t *testing.T) {
2559    const input = `package main
2560 var _ = &bytes.Buffer{}`
2561
2562    const want = `package main
2563
2564import "bytes"
2565
2566var _ = &bytes.Buffer{}
2567`
2568    testConfig{
2569        modulepackagestest.Module{
2570            Name:  "foo.com",
2571            Filesfm{"x.go""package x\n"},
2572        },
2573    }.processTest(t"foo.com""x.go", []byte(input), nilwant)
2574}
2575
2576func TestImportNoGoFiles(t *testing.T) {
2577    const input = `package main
2578 var _ = &bytes.Buffer{}`
2579
2580    const want = `package main
2581
2582import "bytes"
2583
2584var _ = &bytes.Buffer{}
2585`
2586    testConfig{
2587        modulepackagestest.Module{
2588            Name"mycompany.net",
2589        },
2590    }.test(t, func(t *goimportTest) {
2591        buferr := t.processNonModule("mycompany.net/tool/main.go", []byte(input), nil)
2592        if err != nil {
2593            t.Fatalf("Process() = %v"err)
2594        }
2595        if string(buf) != want {
2596            t.Errorf("Got:\n%s\nWant:\n%s"bufwant)
2597        }
2598    })
2599
2600}
2601
2602// Ensures a token as large as 500000 bytes can be handled
2603// https://golang.org/issues/18201
2604func TestProcessLargeToken(t *testing.T) {
2605    largeString := strings.Repeat("x"500000)
2606
2607    input := `package testimports
2608
2609import (
2610    "bytes"
2611)
2612
2613const s = fmt.Sprintf("%s", "` + largeString + `")
2614var _ = bytes.Buffer{}
2615
2616// end
2617`
2618
2619    want := `package testimports
2620
2621import (
2622    "bytes"
2623    "fmt"
2624)
2625
2626const s = fmt.Sprintf("%s", "` + largeString + `")
2627
2628var _ = bytes.Buffer{}
2629
2630// end
2631`
2632
2633    testConfig{
2634        modulepackagestest.Module{
2635            Name:  "foo.com",
2636            Filesfm{"foo.go"input},
2637        },
2638    }.processTest(t"foo.com""foo.go"nilnilwant)
2639}
2640
2641// Tests that an external test package will import the package under test if it
2642// also uses symbols exported only in test files.
2643// https://golang.org/issues/29979
2644func TestExternalTest(t *testing.T) {
2645    const input = `package a_test
2646func TestX() {
2647    a.X()
2648    a.Y()
2649}
2650`
2651    const want = `package a_test
2652
2653import "foo.com/a"
2654
2655func TestX() {
2656    a.X()
2657    a.Y()
2658}
2659`
2660
2661    testConfig{
2662        modules: []packagestest.Module{
2663            {
2664                Name"foo.com/a",
2665                Filesfm{
2666                    "a.go":           "package a\n func X() {}",
2667                    "export_test.go""package a\n func Y() {}",
2668                    "a_test.go":      input,
2669                },
2670            },
2671        },
2672    }.processTest(t"foo.com/a""a_test.go"nilnilwant)
2673}
2674
2675// TestGetCandidates tests that get packages finds packages
2676// with correct priorities.
2677func TestGetCandidates(t *testing.T) {
2678    type res struct {
2679        relevance  float64
2680        namepath string
2681    }
2682    want := []res{
2683        {0"bytes""bytes"},
2684        {0"http""net/http"},
2685        {0"rand""crypto/rand"},
2686        {0"bar""bar.com/bar"},
2687        {0"foo""foo.com/foo"},
2688    }
2689
2690    testConfig{
2691        modules: []packagestest.Module{
2692            {
2693                Name:  "bar.com",
2694                Filesfm{"bar/bar.go""package bar\n"},
2695            },
2696            {
2697                Name:  "foo.com",
2698                Filesfm{"foo/foo.go""package foo\n"},
2699            },
2700        },
2701    }.test(t, func(t *goimportTest) {
2702        var mu sync.Mutex
2703        var got []res
2704        add := func(c ImportFix) {
2705            mu.Lock()
2706            defer mu.Unlock()
2707            for _w := range want {
2708                if c.StmtInfo.ImportPath == w.path {
2709                    got = append(gotres{c.Relevancec.IdentNamec.StmtInfo.ImportPath})
2710                }
2711            }
2712        }
2713        if err := GetAllCandidates(context.Background(), add"""x.go""x"t.env); err != nil {
2714            t.Fatalf("GetAllCandidates() = %v"err)
2715        }
2716        // Sort, then clear out relevance so it doesn't mess up the DeepEqual.
2717        sort.Slice(got, func(ij intbool {
2718            rirj := got[i], got[j]
2719            if ri.relevance != rj.relevance {
2720                return ri.relevance > rj.relevance // Highest first.
2721            }
2722            return ri.name < rj.name
2723        })
2724        for i := range got {
2725            got[i].relevance = 0
2726        }
2727        if !reflect.DeepEqual(wantgot) {
2728            t.Errorf("wanted results in order %v, got %v"wantgot)
2729        }
2730    })
2731}
2732
2733func TestGetImportPaths(t *testing.T) {
2734    type res struct {
2735        relevance  float64
2736        namepath string
2737    }
2738    want := []res{
2739        {0"http""net/http"},
2740        {0"net""net"},
2741        {0"neta""neta.com/neta"},
2742    }
2743
2744    testConfig{
2745        modules: []packagestest.Module{
2746            {
2747                Name:  "neta.com",
2748                Filesfm{"neta/neta.go""package neta\n"},
2749            },
2750        },
2751    }.test(t, func(t *goimportTest) {
2752        var mu sync.Mutex
2753        var got []res
2754        add := func(c ImportFix) {
2755            mu.Lock()
2756            defer mu.Unlock()
2757            for _w := range want {
2758                if c.StmtInfo.ImportPath == w.path {
2759                    got = append(gotres{c.Relevancec.IdentNamec.StmtInfo.ImportPath})
2760                }
2761            }
2762        }
2763        if err := GetImportPaths(context.Background(), add"ne""x.go""x"t.env); err != nil {
2764            t.Fatalf("GetImportPaths() = %v"err)
2765        }
2766        // Sort, then clear out relevance so it doesn't mess up the DeepEqual.
2767        sort.Slice(got, func(ij intbool {
2768            rirj := got[i], got[j]
2769            if ri.relevance != rj.relevance {
2770                return ri.relevance > rj.relevance // Highest first.
2771            }
2772            return ri.name < rj.name
2773        })
2774        for i := range got {
2775            got[i].relevance = 0
2776        }
2777        if !reflect.DeepEqual(wantgot) {
2778            t.Errorf("wanted results in order %v, got %v"wantgot)
2779        }
2780    })
2781}
2782
2783func TestGetPackageCompletions(t *testing.T) {
2784    type res struct {
2785        relevance          float64
2786        namepathsymbol string
2787    }
2788    want := []res{
2789        {0"rand""math/rand""Seed"},
2790        {0"rand""bar.com/rand""Bar"},
2791    }
2792
2793    testConfig{
2794        modules: []packagestest.Module{
2795            {
2796                Name:  "bar.com",
2797                Filesfm{"rand/bar.go""package rand\nvar Bar int\n"},
2798            },
2799        },
2800    }.test(t, func(t *goimportTest) {
2801        var mu sync.Mutex
2802        var got []res
2803        add := func(c PackageExport) {
2804            mu.Lock()
2805            defer mu.Unlock()
2806            for _csym := range c.Exports {
2807                for _w := range want {
2808                    if c.Fix.StmtInfo.ImportPath == w.path && csym == w.symbol {
2809                        got = append(gotres{c.Fix.Relevancec.Fix.IdentNamec.Fix.StmtInfo.ImportPathcsym})
2810                    }
2811                }
2812            }
2813        }
2814        if err := GetPackageExports(context.Background(), add"rand""x.go""x"t.env); err != nil {
2815            t.Fatalf("getPackageCompletions() = %v"err)
2816        }
2817        // Sort, then clear out relevance so it doesn't mess up the DeepEqual.
2818        sort.Slice(got, func(ij intbool {
2819            rirj := got[i], got[j]
2820            if ri.relevance != rj.relevance {
2821                return ri.relevance > rj.relevance // Highest first.
2822            }
2823            return ri.name < rj.name
2824        })
2825        for i := range got {
2826            got[i].relevance = 0
2827        }
2828        if !reflect.DeepEqual(wantgot) {
2829            t.Errorf("wanted results in order %v, got %v"wantgot)
2830        }
2831    })
2832}
2833
2834// Tests #34895: process should not panic on concurrent calls.
2835func TestConcurrentProcess(t *testing.T) {
2836    testConfig{
2837        modulepackagestest.Module{
2838            Name"foo.com",
2839            Filesfm{
2840                "p/first.go"`package foo
2841
2842func _() {
2843    fmt.Println()
2844}
2845`,
2846                "p/second.go"`package foo
2847
2848import "fmt"
2849
2850func _() {
2851    fmt.Println()
2852    imports.Bar() // not imported.
2853}
2854`,
2855            },
2856        },
2857    }.test(t, func(t *goimportTest) {
2858        var (
2859            n  = 10
2860            wg sync.WaitGroup
2861        )
2862        wg.Add(n)
2863        for i := 0i < ni++ {
2864            go func() {
2865                defer wg.Done()
2866                _err := t.process("foo.com""p/first.go"nilnil)
2867                if err != nil {
2868                    t.Error(err)
2869                }
2870            }()
2871        }
2872        wg.Wait()
2873    })
2874}
2875
2876func TestNonlocalDot(t *testing.T) {
2877    const input = `package main
2878import (
2879    "fmt"
2880)
2881var _, _ = fmt.Sprintf, dot.Dot
2882`
2883    const want = `package main
2884
2885import (
2886    "fmt"
2887    "noninternet/dot.v1/dot"
2888)
2889
2890var _, _ = fmt.Sprintf, dot.Dot
2891`
2892    testConfig{
2893        modules: []packagestest.Module{
2894            {
2895                Name:  "golang.org/fake",
2896                Filesfm{"x.go"input},
2897            },
2898            {
2899                Name"noninternet/dot.v1",
2900                Filesfm{
2901                    "dot/dot.go""package dot\nfunc Dot(){}\n",
2902                },
2903            },
2904        },
2905        gopathOnlytrue// our modules testing setup doesn't allow modules without dots.
2906    }.processTest(t"golang.org/fake""x.go"nilnilwant)
2907}
2908
MembersX
testConfig
TestSkipNodeModules
TestFindImportInLocalGoFiles.input
TestFindImportInLocalGoFiles.want
TestRenameWhenPackageNameMismatch.input
TestModuleVersion.input
TestFindStdlib
TestStdlibNotPrefixed.t
testConfig.processTest
TestInMemoryFile.want
TestGetImportPaths.res.path
TestSimpleCases.RangeStmt_15042.tt
fm
goimportTest.process
TestPanic51916
TestStdlibNotPrefixed.savedStdlib
testConfig.processTest.t
goimportTest.process.opts
TestGlobalImports_DifferentPackage.declaresGlobal
TestImportNoGoFiles.BlockStmt.buf
TestGetCandidates.BlockStmt.mu
TestGetPackageCompletions.res.relevance
TestStdlibSelfImports.input
TestImportPathToNameGoPathParse.BlockStmt.srcDir
TestGlobalImports.declaresGlobal
TestGlobalImports_DifferentPackage
TestVendorPackage.input
TestFindStdlib.RangeStmt_22611.BlockStmt.input
goimportTest.process.file
TestGetImportPaths.t
testConfig.test.c
TestLocalPrefix.tests
TestSiblingImport_Misnamed
TestGetCandidates.res.path
TestFindStdlib.RangeStmt_22611.BlockStmt.BlockStmt.buf
TestStdlibNotPrefixed.BlockStmt.err
goimportTest.exported
TestGlobalImports_MultipleMains.want
TestGetCandidates.res
TestFindStdlib.RangeStmt_22611.BlockStmt.BlockStmt.got
TestStdlibSelfImports.t
TestPkgIsCandidate
TestLocalPackagePromotion.want
TestFindStdlib.RangeStmt_22611.BlockStmt.BlockStmt.err
testConfig.modules
TestExternalTest.want
TestConcurrentProcess.BlockStmt.wg
TestProcessVendor
goimportTest.process.t
goimportTest.processNonModule.opts
TestGetImportPaths.res.relevance
TestAppengine
TestRenameWhenPackageNameMismatch.t
TestGetImportPaths.res
TestLocalPackagePromotion.t
TestNonlocalDot.input
TestImportNoGoFiles
TestGetPackageCompletions.BlockStmt.mu
TestConcurrentProcess.BlockStmt.BlockStmt.BlockStmt.err
TestSimpleCases
TestStdlibNotPrefixed.input
testConfig.processTest.contents
goimportTest.assertProcessEquals.err
testConfig.processTest.file
TestAddNameToMismatchedImport.input
TestStdlibNotPrefixed.want
TestImportPathToNameGoPathParse.t
TestIgnoreOwnPackage
TestProcessLargeToken.t
TestFindStdlib.RangeStmt_22611.tt
TestIgnoreDocumentationPackage.t
TestGetCandidates
TestGetImportPaths.BlockStmt.RangeStmt_50678.i
flag
TestImportSymlinksWithIgnore.input
TestRenameWhenPackageNameMismatch.want
TestPanic51916.t
TestSkipNodeModules.t
TestReadFromFilesystem
TestIgnoreDocumentationPackage
TestSiblingImport_Misnamed.t
TestGetPackageCompletions.BlockStmt.err
TestProcessStdin.BlockStmt.err
TestLocalPackagePromotion.input
TestGetPackageCompletions.BlockStmt.BlockStmt.RangeStmt_51343.BlockStmt.RangeStmt_51380.w
TestConcurrentProcess.t
TestSimpleCases.t
TestReadFromFilesystem.tests
TestVendorPackage.t
TestLocalPrefix.RangeStmt_32804.tt
TestLocalPrefix.t
TestExternalTest.input
TestGetImportPaths.BlockStmt.mu
TestNonlocalDot.t
TestGlobalImports_MultipleMains.declaresGlobal
TestImportNoGoFiles.t
TestGetCandidates.t
TestGetPackageCompletions.BlockStmt.got
TestAppengine.t
TestInternal.importAdded
TestProcessVendor.t
goimportTest.assertProcessEquals.module
TestImportNoGoFiles.input
TestGetCandidates.BlockStmt.got
goimportTest.assertProcessEquals.t
TestExternalTestImportsPackageUnderTest.t
TestGetPackageCompletions.want
TestIgnoreConfiguration.want
TestSiblingImports
TestGlobalImports.usesGlobal
TestExternalTestImportsPackageUnderTest
TestSimpleCases.localPrefix
TestImportSymlinksWithIgnore
goimportTest.processNonModule
TestRenameWhenPackageNameMismatch
TestImportSymlinks.want
TestPanicAstutils
TestGetPackageCompletions.res.path
TestExternalTestImportsPackageUnderTest.want
TestGetPackageCompletions.BlockStmt.BlockStmt.RangeStmt_51343.csym
TestImportPathToNameGoPathParse
TestSkipNodeModules.want
TestSiblingImports.need
TestIgnoreOwnPackage.input
testConfig.gopathOnly
goimportTest.process.contents
TestLocalPrefix
TestExternalTest
TestPanic51916.want
TestProcessLargeToken
TestGetPackageCompletions.BlockStmt.RangeStmt_52016.i
log
TestFindStdlib.t
testConfig.processTest.c
goimportTest
TestPanic51916.input
TestReadFromFilesystem.t
TestProcessVendor.input
TestNonlocalDot
TestGlobalImports_MultipleMains.input
TestGetPackageCompletions.res
TestConcurrentProcess.BlockStmt.n
TestFindStdlib.RangeStmt_22611.BlockStmt.RangeStmt_22665.sym
goimportTest.processNonModule.file
TestIgnoreOwnPackage.want
TestProcessStdin.t
TestFindStdlib.tests
testConfig.module
TestGlobalImports_DifferentPackage.input
TestExternalTestImportsPackageUnderTest.provide
testConfig.test.t
goimportTest.assertProcessEquals
TestSiblingImport_Misnamed.input
TestGetImportPaths.BlockStmt.BlockStmt.RangeStmt_50105.w
TestSimpleCases.RangeStmt_15042.BlockStmt.BlockStmt.BlockStmt.options
TestAppengine.want
TestIgnoreDocumentationPackage.input
TestExternalTest.t
TestGetCandidates.BlockStmt.BlockStmt.RangeStmt_48897.w
TestGetImportPaths.res.name
TestStdlibNotPrefixed.BlockStmt.got
goimportTest.process.f
goimportTest.assertProcessEquals.contents
TestPkgIsCandidate.RangeStmt_43255.i
TestStdlibSelfImports.BlockStmt.got
TestPkgIsCandidate.RangeStmt_43255.tt
TestImportSymlinks.t
TestInternal.input
TestSiblingImport_Misnamed.want
TestImportNoGoFiles.want
TestGetPackageCompletions.res.name
TestConcurrentProcess.BlockStmt.i
testConfig.test.RangeStmt_24846.BlockStmt.BlockStmt.exported
testConfig.test.RangeStmt_24846.BlockStmt.BlockStmt.RangeStmt_25167.BlockStmt.split
TestLocalPackagePromotion
TestProcessLargeToken.largeString
goimportTest.process.module
TestPkgIsCandidate.tests
testConfig.processTest.module
testConfig.processTest.want
TestAddNameToMismatchedImport.want
TestGetCandidates.want
TestGetImportPaths.want
testConfig.test
TestGlobalImports
TestIgnoreOwnPackage.t
TestImportNoGoFiles.BlockStmt.err
TestImportSymlinks.input
TestSiblingImports.provide
TestInternal
goimportTest.assertProcessEquals.buf
TestConcurrentProcess
goimportTest.env
TestIgnoreConfiguration
TestGetCandidates.res.name
TestGetPackageCompletions.t
goimportTest.processNonModule.BlockStmt.err
TestAddNameToMismatchedImport
TestGetImportPaths.BlockStmt.got
TestConcurrentProcess.BlockStmt.BlockStmt.BlockStmt._
TestPkgIsCandidate.t
TestProcessStdin
TestFindImportInLocalGoFiles.t
testConfig.test.fn
goimportTest.assertProcessEquals.opts
TestLocalPrefix.RangeStmt_32804.BlockStmt.BlockStmt.BlockStmt.options
TestSiblingImports.want
TestGlobalImports_DifferentPackage.t
TestFindImportInLocalGoFiles
TestStdlibNotPrefixed
goimportTest.goroot
goimportTest.assertProcessEquals.want
TestIgnoreConfiguration.input
TestSiblingImport_Misnamed.sibling
TestPkgIsCandidate.RangeStmt_43255.BlockStmt.BlockStmt.refs
TestPkgIsCandidate.RangeStmt_43255.BlockStmt.BlockStmt.got
testConfig.test.RangeStmt_24846.BlockStmt.BlockStmt.env
testConfig.processTest.opts
TestImportPathToNameGoPathParse.BlockStmt.r
TestGlobalImports.t
testConfig.test.RangeStmt_24846.BlockStmt.BlockStmt.RangeStmt_25167.kv
TestAddNameToMismatchedImport.t
TestGlobalImports_DifferentPackage.want
TestGetPackageCompletions.res.symbol
TestReadFromFilesystem.RangeStmt_17732.tt
TestImportSymlinks
TestStdlibSelfImports
TestStdlibSelfImports.BlockStmt.err
TestGetPackageCompletions
TestModuleVersion
TestVendorPackage
TestExternalTestImportsPackageUnderTest.input
TestProcessStdin.BlockStmt.got
TestSiblingImports.t
TestInMemoryFile
TestImportSymlinksWithIgnore.want
TestInternal.t
goimportTest.processNonModule.t
TestImportPathToNameGoPathParse.BlockStmt.names
TestGetCandidates.BlockStmt.err
TestInMemoryFile.input
TestVendorPackage.want
TestProcessVendor.want
testConfig.test.RangeStmt_24846.BlockStmt.BlockStmt.it
TestIgnoreConfiguration.t
TestPanicAstutils.input
packagestest
TestModuleVersion.t
goimportTest.processNonModule.contents
TestPanicAstutils.t
TestImportSymlinksWithIgnore.t
TestImportPathToNameGoPathParse.BlockStmt.want
TestGetCandidates.BlockStmt.RangeStmt_49472.i
testing
goimportTest.assertProcessEquals.file
TestImportPathToNameGoPathParse.BlockStmt.err
TestGetCandidates.res.relevance
TestGlobalImports_MultipleMains
TestInMemoryFile.t
TestGetImportPaths
TestGetImportPaths.BlockStmt.err
TestReadFromFilesystem.RangeStmt_17732.BlockStmt.BlockStmt.options
testConfig.test.RangeStmt_24846.exporter
TestIgnoreDocumentationPackage.want
TestSkipNodeModules.input
TestAppengine.input
TestPanicAstutils.want
TestGlobalImports_MultipleMains.t
TestNonlocalDot.want
Members
X