GoPLS Viewer

Home|gopls/go/ast/astutil/imports_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 astutil
6
7import (
8    "bytes"
9    "go/ast"
10    "go/format"
11    "go/parser"
12    "go/token"
13    "reflect"
14    "strconv"
15    "testing"
16)
17
18var fset = token.NewFileSet()
19
20func parse(t *testing.Tnamein string) *ast.File {
21    fileerr := parser.ParseFile(fsetnameinparser.ParseComments)
22    if err != nil {
23        t.Fatalf("%s parse: %v"nameerr)
24    }
25    return file
26}
27
28func print(t *testing.Tname stringf *ast.Filestring {
29    var buf bytes.Buffer
30    if err := format.Node(&buffsetf); err != nil {
31        t.Fatalf("%s gofmt: %v"nameerr)
32    }
33    return buf.String()
34}
35
36type test struct {
37    name       string
38    renamedPkg string
39    pkg        string
40    in         string
41    out        string
42    unchanged  bool // Expect added/deleted return value to be false.
43}
44
45var addTests = []test{
46    {
47        name"leave os alone",
48        pkg:  "os",
49        in`package main
50
51import (
52    "os"
53)
54`,
55        out`package main
56
57import (
58    "os"
59)
60`,
61        unchangedtrue,
62    },
63    {
64        name"import.1",
65        pkg:  "os",
66        in`package main
67`,
68        out`package main
69
70import "os"
71`,
72    },
73    {
74        name"import.2",
75        pkg:  "os",
76        in`package main
77
78// Comment
79import "C"
80`,
81        out`package main
82
83// Comment
84import "C"
85import "os"
86`,
87    },
88    {
89        name"import.3",
90        pkg:  "os",
91        in`package main
92
93// Comment
94import "C"
95
96import (
97    "io"
98    "utf8"
99)
100`,
101        out`package main
102
103// Comment
104import "C"
105
106import (
107    "io"
108    "os"
109    "utf8"
110)
111`,
112    },
113    {
114        name"import.17",
115        pkg:  "x/y/z",
116        in`package main
117
118// Comment
119import "C"
120
121import (
122    "a"
123    "b"
124
125    "x/w"
126
127    "d/f"
128)
129`,
130        out`package main
131
132// Comment
133import "C"
134
135import (
136    "a"
137    "b"
138
139    "x/w"
140    "x/y/z"
141
142    "d/f"
143)
144`,
145    },
146    {
147        name"issue #19190",
148        pkg:  "x.org/y/z",
149        in`package main
150
151// Comment
152import "C"
153
154import (
155    "bytes"
156    "os"
157
158    "d.com/f"
159)
160`,
161        out`package main
162
163// Comment
164import "C"
165
166import (
167    "bytes"
168    "os"
169
170    "d.com/f"
171    "x.org/y/z"
172)
173`,
174    },
175    {
176        name"issue #19190 with existing grouped import packages",
177        pkg:  "x.org/y/z",
178        in`package main
179
180// Comment
181import "C"
182
183import (
184    "bytes"
185    "os"
186
187    "c.com/f"
188    "d.com/f"
189
190    "y.com/a"
191    "y.com/b"
192    "y.com/c"
193)
194`,
195        out`package main
196
197// Comment
198import "C"
199
200import (
201    "bytes"
202    "os"
203
204    "c.com/f"
205    "d.com/f"
206    "x.org/y/z"
207
208    "y.com/a"
209    "y.com/b"
210    "y.com/c"
211)
212`,
213    },
214    {
215        name"issue #19190 - match score is still respected",
216        pkg:  "y.org/c",
217        in`package main
218
219import (
220    "x.org/a"
221
222    "y.org/b"
223)
224`,
225        out`package main
226
227import (
228    "x.org/a"
229
230    "y.org/b"
231    "y.org/c"
232)
233`,
234    },
235    {
236        name"import into singular group",
237        pkg:  "bytes",
238        in`package main
239
240import "os"
241
242`,
243        out`package main
244
245import (
246    "bytes"
247    "os"
248)
249`,
250    },
251    {
252        name"import into singular group with comment",
253        pkg:  "bytes",
254        in`package main
255
256import /* why */ /* comment here? */ "os"
257
258`,
259        out`package main
260
261import /* why */ /* comment here? */ (
262    "bytes"
263    "os"
264)
265`,
266    },
267    {
268        name"import into group with leading comment",
269        pkg:  "strings",
270        in`package main
271
272import (
273    // comment before bytes
274    "bytes"
275    "os"
276)
277
278`,
279        out`package main
280
281import (
282    // comment before bytes
283    "bytes"
284    "os"
285    "strings"
286)
287`,
288    },
289    {
290        name:       "",
291        renamedPkg"fmtpkg",
292        pkg:        "fmt",
293        in`package main
294
295import "os"
296
297`,
298        out`package main
299
300import (
301    fmtpkg "fmt"
302    "os"
303)
304`,
305    },
306    {
307        name"struct comment",
308        pkg:  "time",
309        in`package main
310
311// This is a comment before a struct.
312type T struct {
313    t  time.Time
314}
315`,
316        out`package main
317
318import "time"
319
320// This is a comment before a struct.
321type T struct {
322    t time.Time
323}
324`,
325    },
326    {
327        name"issue 8729 import C",
328        pkg:  "time",
329        in`package main
330
331import "C"
332
333// comment
334type T time.Time
335`,
336        out`package main
337
338import "C"
339import "time"
340
341// comment
342type T time.Time
343`,
344    },
345    {
346        name"issue 8729 empty import",
347        pkg:  "time",
348        in`package main
349
350import ()
351
352// comment
353type T time.Time
354`,
355        out`package main
356
357import "time"
358
359// comment
360type T time.Time
361`,
362    },
363    {
364        name"issue 8729 comment on package line",
365        pkg:  "time",
366        in`package main // comment
367
368type T time.Time
369`,
370        out`package main // comment
371
372import "time"
373
374type T time.Time
375`,
376    },
377    {
378        name"issue 8729 comment after package",
379        pkg:  "time",
380        in`package main
381// comment
382
383type T time.Time
384`,
385        out`package main
386
387import "time"
388
389// comment
390
391type T time.Time
392`,
393    },
394    {
395        name"issue 8729 comment before and on package line",
396        pkg:  "time",
397        in`// comment before
398package main // comment on
399
400type T time.Time
401`,
402        out`// comment before
403package main // comment on
404
405import "time"
406
407type T time.Time
408`,
409    },
410
411    // Issue 9961: Match prefixes using path segments rather than bytes
412    {
413        name"issue 9961",
414        pkg:  "regexp",
415        in`package main
416
417import (
418    "flag"
419    "testing"
420
421    "rsc.io/p"
422)
423`,
424        out`package main
425
426import (
427    "flag"
428    "regexp"
429    "testing"
430
431    "rsc.io/p"
432)
433`,
434    },
435    // Issue 10337: Preserve comment position
436    {
437        name"issue 10337",
438        pkg:  "fmt",
439        in`package main
440
441import (
442    "bytes" // a
443    "log" // c
444)
445`,
446        out`package main
447
448import (
449    "bytes" // a
450    "fmt"
451    "log" // c
452)
453`,
454    },
455    {
456        name"issue 10337 new import at the start",
457        pkg:  "bytes",
458        in`package main
459
460import (
461    "fmt" // b
462    "log" // c
463)
464`,
465        out`package main
466
467import (
468    "bytes"
469    "fmt" // b
470    "log" // c
471)
472`,
473    },
474    {
475        name"issue 10337 new import at the end",
476        pkg:  "log",
477        in`package main
478
479import (
480    "bytes" // a
481    "fmt" // b
482)
483`,
484        out`package main
485
486import (
487    "bytes" // a
488    "fmt"   // b
489    "log"
490)
491`,
492    },
493    // Issue 14075: Merge import declarations
494    {
495        name"issue 14075",
496        pkg:  "bufio",
497        in`package main
498
499import "bytes"
500import "fmt"
501`,
502        out`package main
503
504import (
505    "bufio"
506    "bytes"
507    "fmt"
508)
509`,
510    },
511    {
512        name"issue 14075 update position",
513        pkg:  "bufio",
514        in`package main
515
516import "bytes"
517import (
518    "fmt"
519)
520`,
521        out`package main
522
523import (
524    "bufio"
525    "bytes"
526    "fmt"
527)
528`,
529    },
530    {
531        name`issue 14075 ignore import "C"`,
532        pkg:  "bufio",
533        in`package main
534
535// Comment
536import "C"
537
538import "bytes"
539import "fmt"
540`,
541        out`package main
542
543// Comment
544import "C"
545
546import (
547    "bufio"
548    "bytes"
549    "fmt"
550)
551`,
552    },
553    {
554        name`issue 14075 ignore adjacent import "C"`,
555        pkg:  "bufio",
556        in`package main
557
558// Comment
559import "C"
560import "fmt"
561`,
562        out`package main
563
564// Comment
565import "C"
566import (
567    "bufio"
568    "fmt"
569)
570`,
571    },
572    {
573        name`issue 14075 ignore adjacent import "C" (without factored import)`,
574        pkg:  "bufio",
575        in`package main
576
577// Comment
578import "C"
579import "fmt"
580`,
581        out`package main
582
583// Comment
584import "C"
585import (
586    "bufio"
587    "fmt"
588)
589`,
590    },
591    {
592        name`issue 14075 ignore single import "C"`,
593        pkg:  "bufio",
594        in`package main
595
596// Comment
597import "C"
598`,
599        out`package main
600
601// Comment
602import "C"
603import "bufio"
604`,
605    },
606    {
607        name`issue 17212 several single-import lines with shared prefix ending in a slash`,
608        pkg:  "net/http",
609        in`package main
610
611import "bufio"
612import "net/url"
613`,
614        out`package main
615
616import (
617    "bufio"
618    "net/http"
619    "net/url"
620)
621`,
622    },
623    {
624        name`issue 17212 block imports lines with shared prefix ending in a slash`,
625        pkg:  "net/http",
626        in`package main
627
628import (
629    "bufio"
630    "net/url"
631)
632`,
633        out`package main
634
635import (
636    "bufio"
637    "net/http"
638    "net/url"
639)
640`,
641    },
642    {
643        name`issue 17213 many single-import lines`,
644        pkg:  "fmt",
645        in`package main
646
647import "bufio"
648import "bytes"
649import "errors"
650`,
651        out`package main
652
653import (
654    "bufio"
655    "bytes"
656    "errors"
657    "fmt"
658)
659`,
660    },
661
662    // Issue 28605: Add specified import, even if that import path is imported under another name
663    {
664        name:       "issue 28605 add unnamed path",
665        renamedPkg"",
666        pkg:        "path",
667        in`package main
668
669import (
670    . "path"
671    _ "path"
672    pathpkg "path"
673)
674`,
675        out`package main
676
677import (
678    "path"
679    . "path"
680    _ "path"
681    pathpkg "path"
682)
683`,
684    },
685    {
686        name:       "issue 28605 add pathpkg-renamed path",
687        renamedPkg"pathpkg",
688        pkg:        "path",
689        in`package main
690
691import (
692    "path"
693    . "path"
694    _ "path"
695)
696`,
697        out`package main
698
699import (
700    "path"
701    . "path"
702    _ "path"
703    pathpkg "path"
704)
705`,
706    },
707    {
708        name:       "issue 28605 add blank identifier path",
709        renamedPkg"_",
710        pkg:        "path",
711        in`package main
712
713import (
714    "path"
715    . "path"
716    pathpkg "path"
717)
718`,
719        out`package main
720
721import (
722    "path"
723    . "path"
724    _ "path"
725    pathpkg "path"
726)
727`,
728    },
729    {
730        name:       "issue 28605 add dot import path",
731        renamedPkg".",
732        pkg:        "path",
733        in`package main
734
735import (
736    "path"
737    _ "path"
738    pathpkg "path"
739)
740`,
741        out`package main
742
743import (
744    "path"
745    . "path"
746    _ "path"
747    pathpkg "path"
748)
749`,
750    },
751
752    {
753        name:       "duplicate import declarations, add existing one",
754        renamedPkg"f",
755        pkg:        "fmt",
756        in`package main
757
758import "fmt"
759import "fmt"
760import f "fmt"
761import f "fmt"
762`,
763        out`package main
764
765import "fmt"
766import "fmt"
767import f "fmt"
768import f "fmt"
769`,
770        unchangedtrue,
771    },
772}
773
774func TestAddImport(t *testing.T) {
775    for _test := range addTests {
776        file := parse(ttest.nametest.in)
777        var before bytes.Buffer
778        ast.Fprint(&beforefsetfilenil)
779        added := AddNamedImport(fsetfiletest.renamedPkgtest.pkg)
780        if got := print(ttest.namefile); got != test.out {
781            t.Errorf("first run: %s:\ngot: %s\nwant: %s"test.namegottest.out)
782            var after bytes.Buffer
783            ast.Fprint(&afterfsetfilenil)
784            t.Logf("AST before:\n%s\nAST after:\n%s\n"before.String(), after.String())
785        }
786        if gotwant := added, !test.unchangedgot != want {
787            t.Errorf("first run: %s: added = %v, want %v"test.namegotwant)
788        }
789
790        // AddNamedImport should be idempotent. Verify that by calling it again,
791        // expecting no change to the AST, and the returned added value to always be false.
792        added = AddNamedImport(fsetfiletest.renamedPkgtest.pkg)
793        if got := print(ttest.namefile); got != test.out {
794            t.Errorf("second run: %s:\ngot: %s\nwant: %s"test.namegottest.out)
795        }
796        if gotwant := addedfalsegot != want {
797            t.Errorf("second run: %s: added = %v, want %v"test.namegotwant)
798        }
799    }
800}
801
802func TestDoubleAddImport(t *testing.T) {
803    file := parse(t"doubleimport""package main\n")
804    AddImport(fsetfile"os")
805    AddImport(fsetfile"bytes")
806    want := `package main
807
808import (
809    "bytes"
810    "os"
811)
812`
813    if got := print(t"doubleimport"file); got != want {
814        t.Errorf("got: %s\nwant: %s"gotwant)
815    }
816}
817
818func TestDoubleAddNamedImport(t *testing.T) {
819    file := parse(t"doublenamedimport""package main\n")
820    AddNamedImport(fsetfile"o""os")
821    AddNamedImport(fsetfile"i""io")
822    want := `package main
823
824import (
825    i "io"
826    o "os"
827)
828`
829    if got := print(t"doublenamedimport"file); got != want {
830        t.Errorf("got: %s\nwant: %s"gotwant)
831    }
832}
833
834// Part of issue 8729.
835func TestDoubleAddImportWithDeclComment(t *testing.T) {
836    file := parse(t"doubleimport"`package main
837
838import (
839)
840
841// comment
842type I int
843`)
844    // The AddImport order here matters.
845    AddImport(fsetfile"golang.org/x/tools/go/ast/astutil")
846    AddImport(fsetfile"os")
847    want := `package main
848
849import (
850    "golang.org/x/tools/go/ast/astutil"
851    "os"
852)
853
854// comment
855type I int
856`
857    if got := print(t"doubleimport_with_decl_comment"file); got != want {
858        t.Errorf("got: %s\nwant: %s"gotwant)
859    }
860}
861
862var deleteTests = []test{
863    {
864        name"import.4",
865        pkg:  "os",
866        in`package main
867
868import (
869    "os"
870)
871`,
872        out`package main
873`,
874    },
875    {
876        name"import.5",
877        pkg:  "os",
878        in`package main
879
880// Comment
881import "C"
882import "os"
883`,
884        out`package main
885
886// Comment
887import "C"
888`,
889    },
890    {
891        name"import.6",
892        pkg:  "os",
893        in`package main
894
895// Comment
896import "C"
897
898import (
899    "io"
900    "os"
901    "utf8"
902)
903`,
904        out`package main
905
906// Comment
907import "C"
908
909import (
910    "io"
911    "utf8"
912)
913`,
914    },
915    {
916        name"import.7",
917        pkg:  "io",
918        in`package main
919
920import (
921    "io"   // a
922    "os"   // b
923    "utf8" // c
924)
925`,
926        out`package main
927
928import (
929    // a
930    "os"   // b
931    "utf8" // c
932)
933`,
934    },
935    {
936        name"import.8",
937        pkg:  "os",
938        in`package main
939
940import (
941    "io"   // a
942    "os"   // b
943    "utf8" // c
944)
945`,
946        out`package main
947
948import (
949    "io" // a
950    // b
951    "utf8" // c
952)
953`,
954    },
955    {
956        name"import.9",
957        pkg:  "utf8",
958        in`package main
959
960import (
961    "io"   // a
962    "os"   // b
963    "utf8" // c
964)
965`,
966        out`package main
967
968import (
969    "io" // a
970    "os" // b
971    // c
972)
973`,
974    },
975    {
976        name"import.10",
977        pkg:  "io",
978        in`package main
979
980import (
981    "io"
982    "os"
983    "utf8"
984)
985`,
986        out`package main
987
988import (
989    "os"
990    "utf8"
991)
992`,
993    },
994    {
995        name"import.11",
996        pkg:  "os",
997        in`package main
998
999import (
1000    "io"
1001    "os"
1002    "utf8"
1003)
1004`,
1005        out`package main
1006
1007import (
1008    "io"
1009    "utf8"
1010)
1011`,
1012    },
1013    {
1014        name"import.12",
1015        pkg:  "utf8",
1016        in`package main
1017
1018import (
1019    "io"
1020    "os"
1021    "utf8"
1022)
1023`,
1024        out`package main
1025
1026import (
1027    "io"
1028    "os"
1029)
1030`,
1031    },
1032    {
1033        name"handle.raw.quote.imports",
1034        pkg:  "os",
1035        in:   "package main\n\nimport `os`",
1036        out`package main
1037`,
1038    },
1039    {
1040        name"import.13",
1041        pkg:  "io",
1042        in`package main
1043
1044import (
1045    "fmt"
1046
1047    "io"
1048    "os"
1049    "utf8"
1050
1051    "go/format"
1052)
1053`,
1054        out`package main
1055
1056import (
1057    "fmt"
1058
1059    "os"
1060    "utf8"
1061
1062    "go/format"
1063)
1064`,
1065    },
1066    {
1067        name"import.14",
1068        pkg:  "io",
1069        in`package main
1070
1071import (
1072    "fmt" // a
1073
1074    "io"   // b
1075    "os"   // c
1076    "utf8" // d
1077
1078    "go/format" // e
1079)
1080`,
1081        out`package main
1082
1083import (
1084    "fmt" // a
1085
1086    // b
1087    "os"   // c
1088    "utf8" // d
1089
1090    "go/format" // e
1091)
1092`,
1093    },
1094    {
1095        name"import.15",
1096        pkg:  "double",
1097        in`package main
1098
1099import (
1100    "double"
1101    "double"
1102)
1103`,
1104        out`package main
1105`,
1106    },
1107    {
1108        name"import.16",
1109        pkg:  "bubble",
1110        in`package main
1111
1112import (
1113    "toil"
1114    "bubble"
1115    "bubble"
1116    "trouble"
1117)
1118`,
1119        out`package main
1120
1121import (
1122    "toil"
1123    "trouble"
1124)
1125`,
1126    },
1127    {
1128        name"import.17",
1129        pkg:  "quad",
1130        in`package main
1131
1132import (
1133    "quad"
1134    "quad"
1135)
1136
1137import (
1138    "quad"
1139    "quad"
1140)
1141`,
1142        out`package main
1143`,
1144    },
1145    {
1146        name:       "import.18",
1147        renamedPkg"x",
1148        pkg:        "fmt",
1149        in`package main
1150
1151import (
1152    "fmt"
1153    x "fmt"
1154)
1155`,
1156        out`package main
1157
1158import (
1159    "fmt"
1160)
1161`,
1162    },
1163    {
1164        name:       "import.18",
1165        renamedPkg"x",
1166        pkg:        "fmt",
1167        in`package main
1168
1169import x "fmt"
1170import y "fmt"
1171`,
1172        out`package main
1173
1174import y "fmt"
1175`,
1176    },
1177    // Issue #15432, #18051
1178    {
1179        name"import.19",
1180        pkg:  "fmt",
1181        in`package main
1182
1183import (
1184    "fmt"
1185
1186    // Some comment.
1187    "io"
1188)`,
1189        out`package main
1190
1191import (
1192    // Some comment.
1193    "io"
1194)
1195`,
1196    },
1197    {
1198        name"import.20",
1199        pkg:  "fmt",
1200        in`package main
1201
1202import (
1203    "fmt"
1204
1205    // Some
1206    // comment.
1207    "io"
1208)`,
1209        out`package main
1210
1211import (
1212    // Some
1213    // comment.
1214    "io"
1215)
1216`,
1217    },
1218    {
1219        name"import.21",
1220        pkg:  "fmt",
1221        in`package main
1222
1223import (
1224    "fmt"
1225
1226    /*
1227        Some
1228        comment.
1229    */
1230    "io"
1231)`,
1232        out`package main
1233
1234import (
1235    /*
1236        Some
1237        comment.
1238    */
1239    "io"
1240)
1241`,
1242    },
1243    {
1244        name"import.22",
1245        pkg:  "fmt",
1246        in`package main
1247
1248import (
1249    /* Some */
1250    // comment.
1251    "io"
1252    "fmt"
1253)`,
1254        out`package main
1255
1256import (
1257    /* Some */
1258    // comment.
1259    "io"
1260)
1261`,
1262    },
1263    {
1264        name"import.23",
1265        pkg:  "fmt",
1266        in`package main
1267
1268import (
1269    // comment 1
1270    "fmt"
1271    // comment 2
1272    "io"
1273)`,
1274        out`package main
1275
1276import (
1277    // comment 2
1278    "io"
1279)
1280`,
1281    },
1282    {
1283        name"import.24",
1284        pkg:  "fmt",
1285        in`package main
1286
1287import (
1288    "fmt" // comment 1
1289    "io" // comment 2
1290)`,
1291        out`package main
1292
1293import (
1294    "io" // comment 2
1295)
1296`,
1297    },
1298    {
1299        name"import.25",
1300        pkg:  "fmt",
1301        in`package main
1302
1303import (
1304    "fmt"
1305    /* comment */ "io"
1306)`,
1307        out`package main
1308
1309import (
1310    /* comment */ "io"
1311)
1312`,
1313    },
1314    {
1315        name"import.26",
1316        pkg:  "fmt",
1317        in`package main
1318
1319import (
1320    "fmt"
1321    "io" /* comment */
1322)`,
1323        out`package main
1324
1325import (
1326    "io" /* comment */
1327)
1328`,
1329    },
1330    {
1331        name"import.27",
1332        pkg:  "fmt",
1333        in`package main
1334
1335import (
1336    "fmt" /* comment */
1337    "io"
1338)`,
1339        out`package main
1340
1341import (
1342    "io"
1343)
1344`,
1345    },
1346    {
1347        name"import.28",
1348        pkg:  "fmt",
1349        in`package main
1350
1351import (
1352    /* comment */  "fmt"
1353    "io"
1354)`,
1355        out`package main
1356
1357import (
1358    "io"
1359)
1360`,
1361    },
1362    {
1363        name"import.29",
1364        pkg:  "fmt",
1365        in`package main
1366
1367// comment 1
1368import (
1369    "fmt"
1370    "io" // comment 2
1371)`,
1372        out`package main
1373
1374// comment 1
1375import (
1376    "io" // comment 2
1377)
1378`,
1379    },
1380    {
1381        name"import.30",
1382        pkg:  "fmt",
1383        in`package main
1384
1385// comment 1
1386import (
1387    "fmt" // comment 2
1388    "io"
1389)`,
1390        out`package main
1391
1392// comment 1
1393import (
1394    "io"
1395)
1396`,
1397    },
1398    {
1399        name"import.31",
1400        pkg:  "fmt",
1401        in`package main
1402
1403// comment 1
1404import (
1405    "fmt"
1406    /* comment 2 */ "io"
1407)`,
1408        out`package main
1409
1410// comment 1
1411import (
1412    /* comment 2 */ "io"
1413)
1414`,
1415    },
1416    {
1417        name:       "import.32",
1418        pkg:        "fmt",
1419        renamedPkg"f",
1420        in`package main
1421
1422// comment 1
1423import (
1424    f "fmt"
1425    /* comment 2 */ i "io"
1426)`,
1427        out`package main
1428
1429// comment 1
1430import (
1431    /* comment 2 */ i "io"
1432)
1433`,
1434    },
1435    {
1436        name:       "import.33",
1437        pkg:        "fmt",
1438        renamedPkg"f",
1439        in`package main
1440
1441// comment 1
1442import (
1443    /* comment 2 */ f "fmt"
1444    i "io"
1445)`,
1446        out`package main
1447
1448// comment 1
1449import (
1450    i "io"
1451)
1452`,
1453    },
1454    {
1455        name:       "import.34",
1456        pkg:        "fmt",
1457        renamedPkg"f",
1458        in`package main
1459
1460// comment 1
1461import (
1462    f "fmt" /* comment 2 */
1463    i "io"
1464)`,
1465        out`package main
1466
1467// comment 1
1468import (
1469    i "io"
1470)
1471`,
1472    },
1473    {
1474        name"import.35",
1475        pkg:  "fmt",
1476        in`package main
1477
1478// comment 1
1479import (
1480    "fmt"
1481    // comment 2
1482    "io"
1483)`,
1484        out`package main
1485
1486// comment 1
1487import (
1488    // comment 2
1489    "io"
1490)
1491`,
1492    },
1493    {
1494        name"import.36",
1495        pkg:  "fmt",
1496        in`package main
1497
1498/* comment 1 */
1499import (
1500    "fmt"
1501    /* comment 2 */
1502    "io"
1503)`,
1504        out`package main
1505
1506/* comment 1 */
1507import (
1508    /* comment 2 */
1509    "io"
1510)
1511`,
1512    },
1513
1514    // Issue 20229: MergeLine panic on weird input
1515    {
1516        name"import.37",
1517        pkg:  "io",
1518        in`package main
1519import("_"
1520"io")`,
1521        out`package main
1522
1523import (
1524    "_"
1525)
1526`,
1527    },
1528
1529    // Issue 28605: Delete specified import, even if that import path is imported under another name
1530    {
1531        name:       "import.38",
1532        renamedPkg"",
1533        pkg:        "path",
1534        in`package main
1535
1536import (
1537    "path"
1538    . "path"
1539    _ "path"
1540    pathpkg "path"
1541)
1542`,
1543        out`package main
1544
1545import (
1546    . "path"
1547    _ "path"
1548    pathpkg "path"
1549)
1550`,
1551    },
1552    {
1553        name:       "import.39",
1554        renamedPkg"pathpkg",
1555        pkg:        "path",
1556        in`package main
1557
1558import (
1559    "path"
1560    . "path"
1561    _ "path"
1562    pathpkg "path"
1563)
1564`,
1565        out`package main
1566
1567import (
1568    "path"
1569    . "path"
1570    _ "path"
1571)
1572`,
1573    },
1574    {
1575        name:       "import.40",
1576        renamedPkg"_",
1577        pkg:        "path",
1578        in`package main
1579
1580import (
1581    "path"
1582    . "path"
1583    _ "path"
1584    pathpkg "path"
1585)
1586`,
1587        out`package main
1588
1589import (
1590    "path"
1591    . "path"
1592    pathpkg "path"
1593)
1594`,
1595    },
1596    {
1597        name:       "import.41",
1598        renamedPkg".",
1599        pkg:        "path",
1600        in`package main
1601
1602import (
1603    "path"
1604    . "path"
1605    _ "path"
1606    pathpkg "path"
1607)
1608`,
1609        out`package main
1610
1611import (
1612    "path"
1613    _ "path"
1614    pathpkg "path"
1615)
1616`,
1617    },
1618
1619    // Duplicate import declarations, all matching ones are deleted.
1620    {
1621        name:       "import.42",
1622        renamedPkg"f",
1623        pkg:        "fmt",
1624        in`package main
1625
1626import "fmt"
1627import "fmt"
1628import f "fmt"
1629import f "fmt"
1630`,
1631        out`package main
1632
1633import "fmt"
1634import "fmt"
1635`,
1636    },
1637    {
1638        name:       "import.43",
1639        renamedPkg"x",
1640        pkg:        "fmt",
1641        in`package main
1642
1643import "fmt"
1644import "fmt"
1645import f "fmt"
1646import f "fmt"
1647`,
1648        out`package main
1649
1650import "fmt"
1651import "fmt"
1652import f "fmt"
1653import f "fmt"
1654`,
1655        unchangedtrue,
1656    },
1657    // this test panics without PositionFor in DeleteNamedImport
1658    {
1659        name:       "import.44",
1660        pkg:        "foo.com/other/v3",
1661        renamedPkg"",
1662        in`package main
1663//line mah.go:600
1664
1665import (
1666"foo.com/a.thing"
1667"foo.com/surprise"
1668"foo.com/v1"
1669"foo.com/other/v2"
1670"foo.com/other/v3"
1671)
1672`,
1673        out`package main
1674
1675//line mah.go:600
1676
1677import (
1678    "foo.com/a.thing"
1679    "foo.com/other/v2"
1680    "foo.com/surprise"
1681    "foo.com/v1"
1682)
1683`,
1684    },
1685}
1686
1687func TestDeleteImport(t *testing.T) {
1688    for _test := range deleteTests {
1689        file := parse(ttest.nametest.in)
1690        var before bytes.Buffer
1691        ast.Fprint(&beforefsetfilenil)
1692        deleted := DeleteNamedImport(fsetfiletest.renamedPkgtest.pkg)
1693        if got := print(ttest.namefile); got != test.out {
1694            t.Errorf("first run: %s:\ngot: %s\nwant: %s"test.namegottest.out)
1695            var after bytes.Buffer
1696            ast.Fprint(&afterfsetfilenil)
1697            t.Logf("AST before:\n%s\nAST after:\n%s\n"before.String(), after.String())
1698        }
1699        if gotwant := deleted, !test.unchangedgot != want {
1700            t.Errorf("first run: %s: deleted = %v, want %v"test.namegotwant)
1701        }
1702
1703        // DeleteNamedImport should be idempotent. Verify that by calling it again,
1704        // expecting no change to the AST, and the returned deleted value to always be false.
1705        deleted = DeleteNamedImport(fsetfiletest.renamedPkgtest.pkg)
1706        if got := print(ttest.namefile); got != test.out {
1707            t.Errorf("second run: %s:\ngot: %s\nwant: %s"test.namegottest.out)
1708        }
1709        if gotwant := deletedfalsegot != want {
1710            t.Errorf("second run: %s: deleted = %v, want %v"test.namegotwant)
1711        }
1712    }
1713}
1714
1715func TestDeleteImportAfterAddImport(t *testing.T) {
1716    file := parse(t"test"`package main
1717
1718import "os"
1719`)
1720    if gotwant := AddImport(fsetfile"fmt"), truegot != want {
1721        t.Errorf("AddImport: got: %v, want: %v"gotwant)
1722    }
1723    if gotwant := DeleteImport(fsetfile"fmt"), truegot != want {
1724        t.Errorf("DeleteImport: got: %v, want: %v"gotwant)
1725    }
1726}
1727
1728type rewriteTest struct {
1729    name   string
1730    srcPkg string
1731    dstPkg string
1732    in     string
1733    out    string
1734}
1735
1736var rewriteTests = []rewriteTest{
1737    {
1738        name:   "import.13",
1739        srcPkg"utf8",
1740        dstPkg"encoding/utf8",
1741        in`package main
1742
1743import (
1744    "io"
1745    "os"
1746    "utf8" // thanks ken
1747)
1748`,
1749        out`package main
1750
1751import (
1752    "encoding/utf8" // thanks ken
1753    "io"
1754    "os"
1755)
1756`,
1757    },
1758    {
1759        name:   "import.14",
1760        srcPkg"asn1",
1761        dstPkg"encoding/asn1",
1762        in`package main
1763
1764import (
1765    "asn1"
1766    "crypto"
1767    "crypto/rsa"
1768    _ "crypto/sha1"
1769    "crypto/x509"
1770    "crypto/x509/pkix"
1771    "time"
1772)
1773
1774var x = 1
1775`,
1776        out`package main
1777
1778import (
1779    "crypto"
1780    "crypto/rsa"
1781    _ "crypto/sha1"
1782    "crypto/x509"
1783    "crypto/x509/pkix"
1784    "encoding/asn1"
1785    "time"
1786)
1787
1788var x = 1
1789`,
1790    },
1791    {
1792        name:   "import.15",
1793        srcPkg"url",
1794        dstPkg"net/url",
1795        in`package main
1796
1797import (
1798    "bufio"
1799    "net"
1800    "path"
1801    "url"
1802)
1803
1804var x = 1 // comment on x, not on url
1805`,
1806        out`package main
1807
1808import (
1809    "bufio"
1810    "net"
1811    "net/url"
1812    "path"
1813)
1814
1815var x = 1 // comment on x, not on url
1816`,
1817    },
1818    {
1819        name:   "import.16",
1820        srcPkg"http",
1821        dstPkg"net/http",
1822        in`package main
1823
1824import (
1825    "flag"
1826    "http"
1827    "log"
1828    "text/template"
1829)
1830
1831var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
1832`,
1833        out`package main
1834
1835import (
1836    "flag"
1837    "log"
1838    "net/http"
1839    "text/template"
1840)
1841
1842var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
1843`,
1844    },
1845}
1846
1847func TestRewriteImport(t *testing.T) {
1848    for _test := range rewriteTests {
1849        file := parse(ttest.nametest.in)
1850        RewriteImport(fsetfiletest.srcPkgtest.dstPkg)
1851        if got := print(ttest.namefile); got != test.out {
1852            t.Errorf("%s:\ngot: %s\nwant: %s"test.namegottest.out)
1853        }
1854    }
1855}
1856
1857var importsTests = []struct {
1858    name string
1859    in   string
1860    want [][]string
1861}{
1862    {
1863        name"no packages",
1864        in`package foo
1865`,
1866        wantnil,
1867    },
1868    {
1869        name"one group",
1870        in`package foo
1871
1872import (
1873    "fmt"
1874    "testing"
1875)
1876`,
1877        want: [][]string{{"fmt""testing"}},
1878    },
1879    {
1880        name"four groups",
1881        in`package foo
1882
1883import "C"
1884import (
1885    "fmt"
1886    "testing"
1887
1888    "appengine"
1889
1890    "myproject/mylib1"
1891    "myproject/mylib2"
1892)
1893`,
1894        want: [][]string{
1895            {"C"},
1896            {"fmt""testing"},
1897            {"appengine"},
1898            {"myproject/mylib1""myproject/mylib2"},
1899        },
1900    },
1901    {
1902        name"multiple factored groups",
1903        in`package foo
1904
1905import (
1906    "fmt"
1907    "testing"
1908
1909    "appengine"
1910)
1911import (
1912    "reflect"
1913
1914    "bytes"
1915)
1916`,
1917        want: [][]string{
1918            {"fmt""testing"},
1919            {"appengine"},
1920            {"reflect"},
1921            {"bytes"},
1922        },
1923    },
1924}
1925
1926func unquote(s stringstring {
1927    reserr := strconv.Unquote(s)
1928    if err != nil {
1929        return "could_not_unquote"
1930    }
1931    return res
1932}
1933
1934func TestImports(t *testing.T) {
1935    fset := token.NewFileSet()
1936    for _test := range importsTests {
1937        ferr := parser.ParseFile(fset"test.go"test.in0)
1938        if err != nil {
1939            t.Errorf("%s: %v"test.nameerr)
1940            continue
1941        }
1942        var got [][]string
1943        for _group := range Imports(fsetf) {
1944            var b []string
1945            for _spec := range group {
1946                b = append(bunquote(spec.Path.Value))
1947            }
1948            got = append(gotb)
1949        }
1950        if !reflect.DeepEqual(gottest.want) {
1951            t.Errorf("Imports(%s)=%v, want %v"test.namegottest.want)
1952        }
1953    }
1954}
1955
1956var usesImportTests = []struct {
1957    name string
1958    path string
1959    in   string
1960    want bool
1961}{
1962    {
1963        name"no packages",
1964        path"io",
1965        in`package foo
1966`,
1967        wantfalse,
1968    },
1969    {
1970        name"import.1",
1971        path"io",
1972        in`package foo
1973
1974import "io"
1975
1976var _ io.Writer
1977`,
1978        wanttrue,
1979    },
1980    {
1981        name"import.2",
1982        path"io",
1983        in`package foo
1984
1985import "io"
1986`,
1987        wantfalse,
1988    },
1989    {
1990        name"import.3",
1991        path"io",
1992        in`package foo
1993
1994import "io"
1995
1996var io = 42
1997`,
1998        wantfalse,
1999    },
2000    {
2001        name"import.4",
2002        path"io",
2003        in`package foo
2004
2005import i "io"
2006
2007var _ i.Writer
2008`,
2009        wanttrue,
2010    },
2011    {
2012        name"import.5",
2013        path"io",
2014        in`package foo
2015
2016import i "io"
2017`,
2018        wantfalse,
2019    },
2020    {
2021        name"import.6",
2022        path"io",
2023        in`package foo
2024
2025import i "io"
2026
2027var i = 42
2028var io = 42
2029`,
2030        wantfalse,
2031    },
2032    {
2033        name"import.7",
2034        path"encoding/json",
2035        in`package foo
2036
2037import "encoding/json"
2038
2039var _ json.Encoder
2040`,
2041        wanttrue,
2042    },
2043    {
2044        name"import.8",
2045        path"encoding/json",
2046        in`package foo
2047
2048import "encoding/json"
2049`,
2050        wantfalse,
2051    },
2052    {
2053        name"import.9",
2054        path"encoding/json",
2055        in`package foo
2056
2057import "encoding/json"
2058
2059var json = 42
2060`,
2061        wantfalse,
2062    },
2063    {
2064        name"import.10",
2065        path"encoding/json",
2066        in`package foo
2067
2068import j "encoding/json"
2069
2070var _ j.Encoder
2071`,
2072        wanttrue,
2073    },
2074    {
2075        name"import.11",
2076        path"encoding/json",
2077        in`package foo
2078
2079import j "encoding/json"
2080`,
2081        wantfalse,
2082    },
2083    {
2084        name"import.12",
2085        path"encoding/json",
2086        in`package foo
2087
2088import j "encoding/json"
2089
2090var j = 42
2091var json = 42
2092`,
2093        wantfalse,
2094    },
2095    {
2096        name"import.13",
2097        path"io",
2098        in`package foo
2099
2100import _ "io"
2101`,
2102        wanttrue,
2103    },
2104    {
2105        name"import.14",
2106        path"io",
2107        in`package foo
2108
2109import . "io"
2110`,
2111        wanttrue,
2112    },
2113}
2114
2115func TestUsesImport(t *testing.T) {
2116    fset := token.NewFileSet()
2117    for _test := range usesImportTests {
2118        ferr := parser.ParseFile(fset"test.go"test.in0)
2119        if err != nil {
2120            t.Errorf("%s: %v"test.nameerr)
2121            continue
2122        }
2123        got := UsesImport(ftest.path)
2124        if got != test.want {
2125            t.Errorf("UsesImport(%s)=%v, want %v"test.namegottest.want)
2126        }
2127    }
2128}
2129
MembersX
TestDoubleAddImport.file
TestRewriteImport
TestImports.t
TestUsesImport.t
TestUsesImport.RangeStmt_25708.BlockStmt.got
parse.err
test.renamedPkg
TestDoubleAddNamedImport
unquote.err
test.unchanged
TestAddImport.t
TestDoubleAddImport
TestDeleteImport.RangeStmt_19281.test
format
reflect
parse.file
print.f
TestImports.RangeStmt_23429.BlockStmt.RangeStmt_23618.group
TestImports.RangeStmt_23429.BlockStmt.RangeStmt_23618.BlockStmt.b
TestDoubleAddImportWithDeclComment.t
TestDoubleAddImportWithDeclComment.want
TestDeleteImport.RangeStmt_19281.BlockStmt.deleted
TestDeleteImportAfterAddImport.got
parse.in
TestAddImport
TestDoubleAddImport.t
TestDoubleAddNamedImport.t
TestRewriteImport.RangeStmt_22209.test
TestRewriteImport.RangeStmt_22209.BlockStmt.file
TestImports
TestDoubleAddImport.want
TestDoubleAddNamedImport.got
rewriteTest.out
parse
print
test.name
TestAddImport.RangeStmt_8775.BlockStmt.file
rewriteTest.in
test.pkg
TestAddImport.RangeStmt_8775.BlockStmt.want
TestDeleteImport.RangeStmt_19281.BlockStmt.got
TestDeleteImport.RangeStmt_19281.BlockStmt.BlockStmt.after
rewriteTest
rewriteTest.name
TestUsesImport.RangeStmt_25708.test
parse.t
test.in
TestDoubleAddImport.got
TestDoubleAddImportWithDeclComment
TestDeleteImport.RangeStmt_19281.BlockStmt.before
TestDeleteImport.RangeStmt_19281.BlockStmt.want
rewriteTest.dstPkg
TestRewriteImport.RangeStmt_22209.BlockStmt.got
parse.name
print.name
TestAddImport.RangeStmt_8775.test
TestDoubleAddImportWithDeclComment.got
unquote.s
TestImports.RangeStmt_23429.test
TestImports.RangeStmt_23429.BlockStmt.got
TestUsesImport.fset
TestDoubleAddNamedImport.want
TestDeleteImport.t
TestDeleteImportAfterAddImport.t
TestRewriteImport.t
print.buf
TestDoubleAddImportWithDeclComment.file
rewriteTest.srcPkg
print.t
print.err
test
TestDeleteImportAfterAddImport.file
TestAddImport.RangeStmt_8775.BlockStmt.added
TestUsesImport
TestDoubleAddNamedImport.file
TestDeleteImportAfterAddImport
TestImports.RangeStmt_23429.BlockStmt.f
TestAddImport.RangeStmt_8775.BlockStmt.BlockStmt.after
TestImports.RangeStmt_23429.BlockStmt.RangeStmt_23618.BlockStmt.RangeStmt_23680.spec
unquote.res
TestImports.fset
TestUsesImport.RangeStmt_25708.BlockStmt.f
test.out
TestAddImport.RangeStmt_8775.BlockStmt.got
TestDeleteImport.RangeStmt_19281.BlockStmt.file
TestDeleteImportAfterAddImport.want
TestUsesImport.RangeStmt_25708.BlockStmt.err
TestAddImport.RangeStmt_8775.BlockStmt.before
TestDeleteImport
unquote
TestImports.RangeStmt_23429.BlockStmt.err
Members
X