github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/go/ast/astutil/imports_test.go (about)

     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  
     5  package astutil
     6  
     7  import (
     8  	"bytes"
     9  	"go/ast"
    10  	"go/format"
    11  	"go/parser"
    12  	"go/token"
    13  	"reflect"
    14  	"strconv"
    15  	"testing"
    16  )
    17  
    18  var fset = token.NewFileSet()
    19  
    20  func parse(t *testing.T, name, in string) *ast.File {
    21  	file, err := parser.ParseFile(fset, name, in, parser.ParseComments)
    22  	if err != nil {
    23  		t.Fatalf("%s parse: %v", name, err)
    24  	}
    25  	return file
    26  }
    27  
    28  func print(t *testing.T, name string, f *ast.File) string {
    29  	var buf bytes.Buffer
    30  	if err := format.Node(&buf, fset, f); err != nil {
    31  		t.Fatalf("%s gofmt: %v", name, err)
    32  	}
    33  	return buf.String()
    34  }
    35  
    36  type 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  
    45  var addTests = []test{
    46  	{
    47  		name: "leave os alone",
    48  		pkg:  "os",
    49  		in: `package main
    50  
    51  import (
    52  	"os"
    53  )
    54  `,
    55  		out: `package main
    56  
    57  import (
    58  	"os"
    59  )
    60  `,
    61  		unchanged: true,
    62  	},
    63  	{
    64  		name: "import.1",
    65  		pkg:  "os",
    66  		in: `package main
    67  `,
    68  		out: `package main
    69  
    70  import "os"
    71  `,
    72  	},
    73  	{
    74  		name: "import.2",
    75  		pkg:  "os",
    76  		in: `package main
    77  
    78  // Comment
    79  import "C"
    80  `,
    81  		out: `package main
    82  
    83  // Comment
    84  import "C"
    85  import "os"
    86  `,
    87  	},
    88  	{
    89  		name: "import.3",
    90  		pkg:  "os",
    91  		in: `package main
    92  
    93  // Comment
    94  import "C"
    95  
    96  import (
    97  	"io"
    98  	"utf8"
    99  )
   100  `,
   101  		out: `package main
   102  
   103  // Comment
   104  import "C"
   105  
   106  import (
   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
   119  import "C"
   120  
   121  import (
   122  	"a"
   123  	"b"
   124  
   125  	"x/w"
   126  
   127  	"d/f"
   128  )
   129  `,
   130  		out: `package main
   131  
   132  // Comment
   133  import "C"
   134  
   135  import (
   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
   152  import "C"
   153  
   154  import (
   155  	"bytes"
   156  	"os"
   157  
   158  	"d.com/f"
   159  )
   160  `,
   161  		out: `package main
   162  
   163  // Comment
   164  import "C"
   165  
   166  import (
   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
   181  import "C"
   182  
   183  import (
   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
   198  import "C"
   199  
   200  import (
   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  
   219  import (
   220  	"x.org/a"
   221  
   222  	"y.org/b"
   223  )
   224  `,
   225  		out: `package main
   226  
   227  import (
   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  
   240  import "os"
   241  
   242  `,
   243  		out: `package main
   244  
   245  import (
   246  	"bytes"
   247  	"os"
   248  )
   249  `,
   250  	},
   251  	{
   252  		name: "import into singular group with comment",
   253  		pkg:  "bytes",
   254  		in: `package main
   255  
   256  import /* why */ /* comment here? */ "os"
   257  
   258  `,
   259  		out: `package main
   260  
   261  import /* 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  
   272  import (
   273  	// comment before bytes
   274  	"bytes"
   275  	"os"
   276  )
   277  
   278  `,
   279  		out: `package main
   280  
   281  import (
   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  
   295  import "os"
   296  
   297  `,
   298  		out: `package main
   299  
   300  import (
   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.
   312  type T struct {
   313  	t  time.Time
   314  }
   315  `,
   316  		out: `package main
   317  
   318  import "time"
   319  
   320  // This is a comment before a struct.
   321  type T struct {
   322  	t time.Time
   323  }
   324  `,
   325  	},
   326  	{
   327  		name: "issue 8729 import C",
   328  		pkg:  "time",
   329  		in: `package main
   330  
   331  import "C"
   332  
   333  // comment
   334  type T time.Time
   335  `,
   336  		out: `package main
   337  
   338  import "C"
   339  import "time"
   340  
   341  // comment
   342  type T time.Time
   343  `,
   344  	},
   345  	{
   346  		name: "issue 8729 empty import",
   347  		pkg:  "time",
   348  		in: `package main
   349  
   350  import ()
   351  
   352  // comment
   353  type T time.Time
   354  `,
   355  		out: `package main
   356  
   357  import "time"
   358  
   359  // comment
   360  type T time.Time
   361  `,
   362  	},
   363  	{
   364  		name: "issue 8729 comment on package line",
   365  		pkg:  "time",
   366  		in: `package main // comment
   367  
   368  type T time.Time
   369  `,
   370  		out: `package main // comment
   371  
   372  import "time"
   373  
   374  type T time.Time
   375  `,
   376  	},
   377  	{
   378  		name: "issue 8729 comment after package",
   379  		pkg:  "time",
   380  		in: `package main
   381  // comment
   382  
   383  type T time.Time
   384  `,
   385  		out: `package main
   386  
   387  import "time"
   388  
   389  // comment
   390  
   391  type T time.Time
   392  `,
   393  	},
   394  	{
   395  		name: "issue 8729 comment before and on package line",
   396  		pkg:  "time",
   397  		in: `// comment before
   398  package main // comment on
   399  
   400  type T time.Time
   401  `,
   402  		out: `// comment before
   403  package main // comment on
   404  
   405  import "time"
   406  
   407  type 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  
   417  import (
   418  	"flag"
   419  	"testing"
   420  
   421  	"rsc.io/p"
   422  )
   423  `,
   424  		out: `package main
   425  
   426  import (
   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  
   441  import (
   442  	"bytes" // a
   443  	"log" // c
   444  )
   445  `,
   446  		out: `package main
   447  
   448  import (
   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  
   460  import (
   461  	"fmt" // b
   462  	"log" // c
   463  )
   464  `,
   465  		out: `package main
   466  
   467  import (
   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  
   479  import (
   480  	"bytes" // a
   481  	"fmt" // b
   482  )
   483  `,
   484  		out: `package main
   485  
   486  import (
   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  
   499  import "bytes"
   500  import "fmt"
   501  `,
   502  		out: `package main
   503  
   504  import (
   505  	"bufio"
   506  	"bytes"
   507  	"fmt"
   508  )
   509  `,
   510  	},
   511  	{
   512  		name: "issue 14075 update position",
   513  		pkg:  "bufio",
   514  		in: `package main
   515  
   516  import "bytes"
   517  import (
   518  	"fmt"
   519  )
   520  `,
   521  		out: `package main
   522  
   523  import (
   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
   536  import "C"
   537  
   538  import "bytes"
   539  import "fmt"
   540  `,
   541  		out: `package main
   542  
   543  // Comment
   544  import "C"
   545  
   546  import (
   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
   559  import "C"
   560  import "fmt"
   561  `,
   562  		out: `package main
   563  
   564  // Comment
   565  import "C"
   566  import (
   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
   578  import "C"
   579  import "fmt"
   580  `,
   581  		out: `package main
   582  
   583  // Comment
   584  import "C"
   585  import (
   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
   597  import "C"
   598  `,
   599  		out: `package main
   600  
   601  // Comment
   602  import "C"
   603  import "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  
   611  import "bufio"
   612  import "net/url"
   613  `,
   614  		out: `package main
   615  
   616  import (
   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  
   628  import (
   629  	"bufio"
   630  	"net/url"
   631  )
   632  `,
   633  		out: `package main
   634  
   635  import (
   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  
   647  import "bufio"
   648  import "bytes"
   649  import "errors"
   650  `,
   651  		out: `package main
   652  
   653  import (
   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  
   669  import (
   670  	. "path"
   671  	_ "path"
   672  	pathpkg "path"
   673  )
   674  `,
   675  		out: `package main
   676  
   677  import (
   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  
   691  import (
   692  	"path"
   693  	. "path"
   694  	_ "path"
   695  )
   696  `,
   697  		out: `package main
   698  
   699  import (
   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  
   713  import (
   714  	"path"
   715  	. "path"
   716  	pathpkg "path"
   717  )
   718  `,
   719  		out: `package main
   720  
   721  import (
   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  
   735  import (
   736  	"path"
   737  	_ "path"
   738  	pathpkg "path"
   739  )
   740  `,
   741  		out: `package main
   742  
   743  import (
   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  
   758  import "fmt"
   759  import "fmt"
   760  import f "fmt"
   761  import f "fmt"
   762  `,
   763  		out: `package main
   764  
   765  import "fmt"
   766  import "fmt"
   767  import f "fmt"
   768  import f "fmt"
   769  `,
   770  		unchanged: true,
   771  	},
   772  }
   773  
   774  func TestAddImport(t *testing.T) {
   775  	for _, test := range addTests {
   776  		file := parse(t, test.name, test.in)
   777  		var before bytes.Buffer
   778  		ast.Fprint(&before, fset, file, nil)
   779  		added := AddNamedImport(fset, file, test.renamedPkg, test.pkg)
   780  		if got := print(t, test.name, file); got != test.out {
   781  			t.Errorf("first run: %s:\ngot: %s\nwant: %s", test.name, got, test.out)
   782  			var after bytes.Buffer
   783  			ast.Fprint(&after, fset, file, nil)
   784  			t.Logf("AST before:\n%s\nAST after:\n%s\n", before.String(), after.String())
   785  		}
   786  		if got, want := added, !test.unchanged; got != want {
   787  			t.Errorf("first run: %s: added = %v, want %v", test.name, got, want)
   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(fset, file, test.renamedPkg, test.pkg)
   793  		if got := print(t, test.name, file); got != test.out {
   794  			t.Errorf("second run: %s:\ngot: %s\nwant: %s", test.name, got, test.out)
   795  		}
   796  		if got, want := added, false; got != want {
   797  			t.Errorf("second run: %s: added = %v, want %v", test.name, got, want)
   798  		}
   799  	}
   800  }
   801  
   802  func TestDoubleAddImport(t *testing.T) {
   803  	file := parse(t, "doubleimport", "package main\n")
   804  	AddImport(fset, file, "os")
   805  	AddImport(fset, file, "bytes")
   806  	want := `package main
   807  
   808  import (
   809  	"bytes"
   810  	"os"
   811  )
   812  `
   813  	if got := print(t, "doubleimport", file); got != want {
   814  		t.Errorf("got: %s\nwant: %s", got, want)
   815  	}
   816  }
   817  
   818  func TestDoubleAddNamedImport(t *testing.T) {
   819  	file := parse(t, "doublenamedimport", "package main\n")
   820  	AddNamedImport(fset, file, "o", "os")
   821  	AddNamedImport(fset, file, "i", "io")
   822  	want := `package main
   823  
   824  import (
   825  	i "io"
   826  	o "os"
   827  )
   828  `
   829  	if got := print(t, "doublenamedimport", file); got != want {
   830  		t.Errorf("got: %s\nwant: %s", got, want)
   831  	}
   832  }
   833  
   834  // Part of issue 8729.
   835  func TestDoubleAddImportWithDeclComment(t *testing.T) {
   836  	file := parse(t, "doubleimport", `package main
   837  
   838  import (
   839  )
   840  
   841  // comment
   842  type I int
   843  `)
   844  	// The AddImport order here matters.
   845  	AddImport(fset, file, "github.com/powerman/golang-tools/go/ast/astutil")
   846  	AddImport(fset, file, "os")
   847  	want := `package main
   848  
   849  import (
   850  	"github.com/powerman/golang-tools/go/ast/astutil"
   851  	"os"
   852  )
   853  
   854  // comment
   855  type I int
   856  `
   857  	if got := print(t, "doubleimport_with_decl_comment", file); got != want {
   858  		t.Errorf("got: %s\nwant: %s", got, want)
   859  	}
   860  }
   861  
   862  var deleteTests = []test{
   863  	{
   864  		name: "import.4",
   865  		pkg:  "os",
   866  		in: `package main
   867  
   868  import (
   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
   881  import "C"
   882  import "os"
   883  `,
   884  		out: `package main
   885  
   886  // Comment
   887  import "C"
   888  `,
   889  	},
   890  	{
   891  		name: "import.6",
   892  		pkg:  "os",
   893  		in: `package main
   894  
   895  // Comment
   896  import "C"
   897  
   898  import (
   899  	"io"
   900  	"os"
   901  	"utf8"
   902  )
   903  `,
   904  		out: `package main
   905  
   906  // Comment
   907  import "C"
   908  
   909  import (
   910  	"io"
   911  	"utf8"
   912  )
   913  `,
   914  	},
   915  	{
   916  		name: "import.7",
   917  		pkg:  "io",
   918  		in: `package main
   919  
   920  import (
   921  	"io"   // a
   922  	"os"   // b
   923  	"utf8" // c
   924  )
   925  `,
   926  		out: `package main
   927  
   928  import (
   929  	// a
   930  	"os"   // b
   931  	"utf8" // c
   932  )
   933  `,
   934  	},
   935  	{
   936  		name: "import.8",
   937  		pkg:  "os",
   938  		in: `package main
   939  
   940  import (
   941  	"io"   // a
   942  	"os"   // b
   943  	"utf8" // c
   944  )
   945  `,
   946  		out: `package main
   947  
   948  import (
   949  	"io" // a
   950  	// b
   951  	"utf8" // c
   952  )
   953  `,
   954  	},
   955  	{
   956  		name: "import.9",
   957  		pkg:  "utf8",
   958  		in: `package main
   959  
   960  import (
   961  	"io"   // a
   962  	"os"   // b
   963  	"utf8" // c
   964  )
   965  `,
   966  		out: `package main
   967  
   968  import (
   969  	"io" // a
   970  	"os" // b
   971  	// c
   972  )
   973  `,
   974  	},
   975  	{
   976  		name: "import.10",
   977  		pkg:  "io",
   978  		in: `package main
   979  
   980  import (
   981  	"io"
   982  	"os"
   983  	"utf8"
   984  )
   985  `,
   986  		out: `package main
   987  
   988  import (
   989  	"os"
   990  	"utf8"
   991  )
   992  `,
   993  	},
   994  	{
   995  		name: "import.11",
   996  		pkg:  "os",
   997  		in: `package main
   998  
   999  import (
  1000  	"io"
  1001  	"os"
  1002  	"utf8"
  1003  )
  1004  `,
  1005  		out: `package main
  1006  
  1007  import (
  1008  	"io"
  1009  	"utf8"
  1010  )
  1011  `,
  1012  	},
  1013  	{
  1014  		name: "import.12",
  1015  		pkg:  "utf8",
  1016  		in: `package main
  1017  
  1018  import (
  1019  	"io"
  1020  	"os"
  1021  	"utf8"
  1022  )
  1023  `,
  1024  		out: `package main
  1025  
  1026  import (
  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  
  1044  import (
  1045  	"fmt"
  1046  
  1047  	"io"
  1048  	"os"
  1049  	"utf8"
  1050  
  1051  	"go/format"
  1052  )
  1053  `,
  1054  		out: `package main
  1055  
  1056  import (
  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  
  1071  import (
  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  
  1083  import (
  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  
  1099  import (
  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  
  1112  import (
  1113  	"toil"
  1114  	"bubble"
  1115  	"bubble"
  1116  	"trouble"
  1117  )
  1118  `,
  1119  		out: `package main
  1120  
  1121  import (
  1122  	"toil"
  1123  	"trouble"
  1124  )
  1125  `,
  1126  	},
  1127  	{
  1128  		name: "import.17",
  1129  		pkg:  "quad",
  1130  		in: `package main
  1131  
  1132  import (
  1133  	"quad"
  1134  	"quad"
  1135  )
  1136  
  1137  import (
  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  
  1151  import (
  1152  	"fmt"
  1153  	x "fmt"
  1154  )
  1155  `,
  1156  		out: `package main
  1157  
  1158  import (
  1159  	"fmt"
  1160  )
  1161  `,
  1162  	},
  1163  	{
  1164  		name:       "import.18",
  1165  		renamedPkg: "x",
  1166  		pkg:        "fmt",
  1167  		in: `package main
  1168  
  1169  import x "fmt"
  1170  import y "fmt"
  1171  `,
  1172  		out: `package main
  1173  
  1174  import y "fmt"
  1175  `,
  1176  	},
  1177  	// Issue #15432, #18051
  1178  	{
  1179  		name: "import.19",
  1180  		pkg:  "fmt",
  1181  		in: `package main
  1182  
  1183  import (
  1184  	"fmt"
  1185  
  1186  	// Some comment.
  1187  	"io"
  1188  )`,
  1189  		out: `package main
  1190  
  1191  import (
  1192  	// Some comment.
  1193  	"io"
  1194  )
  1195  `,
  1196  	},
  1197  	{
  1198  		name: "import.20",
  1199  		pkg:  "fmt",
  1200  		in: `package main
  1201  
  1202  import (
  1203  	"fmt"
  1204  
  1205  	// Some
  1206  	// comment.
  1207  	"io"
  1208  )`,
  1209  		out: `package main
  1210  
  1211  import (
  1212  	// Some
  1213  	// comment.
  1214  	"io"
  1215  )
  1216  `,
  1217  	},
  1218  	{
  1219  		name: "import.21",
  1220  		pkg:  "fmt",
  1221  		in: `package main
  1222  
  1223  import (
  1224  	"fmt"
  1225  
  1226  	/*
  1227  		Some
  1228  		comment.
  1229  	*/
  1230  	"io"
  1231  )`,
  1232  		out: `package main
  1233  
  1234  import (
  1235  	/*
  1236  		Some
  1237  		comment.
  1238  	*/
  1239  	"io"
  1240  )
  1241  `,
  1242  	},
  1243  	{
  1244  		name: "import.22",
  1245  		pkg:  "fmt",
  1246  		in: `package main
  1247  
  1248  import (
  1249  	/* Some */
  1250  	// comment.
  1251  	"io"
  1252  	"fmt"
  1253  )`,
  1254  		out: `package main
  1255  
  1256  import (
  1257  	/* Some */
  1258  	// comment.
  1259  	"io"
  1260  )
  1261  `,
  1262  	},
  1263  	{
  1264  		name: "import.23",
  1265  		pkg:  "fmt",
  1266  		in: `package main
  1267  
  1268  import (
  1269  	// comment 1
  1270  	"fmt"
  1271  	// comment 2
  1272  	"io"
  1273  )`,
  1274  		out: `package main
  1275  
  1276  import (
  1277  	// comment 2
  1278  	"io"
  1279  )
  1280  `,
  1281  	},
  1282  	{
  1283  		name: "import.24",
  1284  		pkg:  "fmt",
  1285  		in: `package main
  1286  
  1287  import (
  1288  	"fmt" // comment 1
  1289  	"io" // comment 2
  1290  )`,
  1291  		out: `package main
  1292  
  1293  import (
  1294  	"io" // comment 2
  1295  )
  1296  `,
  1297  	},
  1298  	{
  1299  		name: "import.25",
  1300  		pkg:  "fmt",
  1301  		in: `package main
  1302  
  1303  import (
  1304  	"fmt"
  1305  	/* comment */ "io"
  1306  )`,
  1307  		out: `package main
  1308  
  1309  import (
  1310  	/* comment */ "io"
  1311  )
  1312  `,
  1313  	},
  1314  	{
  1315  		name: "import.26",
  1316  		pkg:  "fmt",
  1317  		in: `package main
  1318  
  1319  import (
  1320  	"fmt"
  1321  	"io" /* comment */
  1322  )`,
  1323  		out: `package main
  1324  
  1325  import (
  1326  	"io" /* comment */
  1327  )
  1328  `,
  1329  	},
  1330  	{
  1331  		name: "import.27",
  1332  		pkg:  "fmt",
  1333  		in: `package main
  1334  
  1335  import (
  1336  	"fmt" /* comment */
  1337  	"io"
  1338  )`,
  1339  		out: `package main
  1340  
  1341  import (
  1342  	"io"
  1343  )
  1344  `,
  1345  	},
  1346  	{
  1347  		name: "import.28",
  1348  		pkg:  "fmt",
  1349  		in: `package main
  1350  
  1351  import (
  1352  	/* comment */  "fmt"
  1353  	"io"
  1354  )`,
  1355  		out: `package main
  1356  
  1357  import (
  1358  	"io"
  1359  )
  1360  `,
  1361  	},
  1362  	{
  1363  		name: "import.29",
  1364  		pkg:  "fmt",
  1365  		in: `package main
  1366  
  1367  // comment 1
  1368  import (
  1369  	"fmt"
  1370  	"io" // comment 2
  1371  )`,
  1372  		out: `package main
  1373  
  1374  // comment 1
  1375  import (
  1376  	"io" // comment 2
  1377  )
  1378  `,
  1379  	},
  1380  	{
  1381  		name: "import.30",
  1382  		pkg:  "fmt",
  1383  		in: `package main
  1384  
  1385  // comment 1
  1386  import (
  1387  	"fmt" // comment 2
  1388  	"io"
  1389  )`,
  1390  		out: `package main
  1391  
  1392  // comment 1
  1393  import (
  1394  	"io"
  1395  )
  1396  `,
  1397  	},
  1398  	{
  1399  		name: "import.31",
  1400  		pkg:  "fmt",
  1401  		in: `package main
  1402  
  1403  // comment 1
  1404  import (
  1405  	"fmt"
  1406  	/* comment 2 */ "io"
  1407  )`,
  1408  		out: `package main
  1409  
  1410  // comment 1
  1411  import (
  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
  1423  import (
  1424  	f "fmt"
  1425  	/* comment 2 */ i "io"
  1426  )`,
  1427  		out: `package main
  1428  
  1429  // comment 1
  1430  import (
  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
  1442  import (
  1443  	/* comment 2 */ f "fmt"
  1444  	i "io"
  1445  )`,
  1446  		out: `package main
  1447  
  1448  // comment 1
  1449  import (
  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
  1461  import (
  1462  	f "fmt" /* comment 2 */
  1463  	i "io"
  1464  )`,
  1465  		out: `package main
  1466  
  1467  // comment 1
  1468  import (
  1469  	i "io"
  1470  )
  1471  `,
  1472  	},
  1473  	{
  1474  		name: "import.35",
  1475  		pkg:  "fmt",
  1476  		in: `package main
  1477  
  1478  // comment 1
  1479  import (
  1480  	"fmt"
  1481  	// comment 2
  1482  	"io"
  1483  )`,
  1484  		out: `package main
  1485  
  1486  // comment 1
  1487  import (
  1488  	// comment 2
  1489  	"io"
  1490  )
  1491  `,
  1492  	},
  1493  	{
  1494  		name: "import.36",
  1495  		pkg:  "fmt",
  1496  		in: `package main
  1497  
  1498  /* comment 1 */
  1499  import (
  1500  	"fmt"
  1501  	/* comment 2 */
  1502  	"io"
  1503  )`,
  1504  		out: `package main
  1505  
  1506  /* comment 1 */
  1507  import (
  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
  1519  import("_"
  1520  "io")`,
  1521  		out: `package main
  1522  
  1523  import (
  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  
  1536  import (
  1537  	"path"
  1538  	. "path"
  1539  	_ "path"
  1540  	pathpkg "path"
  1541  )
  1542  `,
  1543  		out: `package main
  1544  
  1545  import (
  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  
  1558  import (
  1559  	"path"
  1560  	. "path"
  1561  	_ "path"
  1562  	pathpkg "path"
  1563  )
  1564  `,
  1565  		out: `package main
  1566  
  1567  import (
  1568  	"path"
  1569  	. "path"
  1570  	_ "path"
  1571  )
  1572  `,
  1573  	},
  1574  	{
  1575  		name:       "import.40",
  1576  		renamedPkg: "_",
  1577  		pkg:        "path",
  1578  		in: `package main
  1579  
  1580  import (
  1581  	"path"
  1582  	. "path"
  1583  	_ "path"
  1584  	pathpkg "path"
  1585  )
  1586  `,
  1587  		out: `package main
  1588  
  1589  import (
  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  
  1602  import (
  1603  	"path"
  1604  	. "path"
  1605  	_ "path"
  1606  	pathpkg "path"
  1607  )
  1608  `,
  1609  		out: `package main
  1610  
  1611  import (
  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  
  1626  import "fmt"
  1627  import "fmt"
  1628  import f "fmt"
  1629  import f "fmt"
  1630  `,
  1631  		out: `package main
  1632  
  1633  import "fmt"
  1634  import "fmt"
  1635  `,
  1636  	},
  1637  	{
  1638  		name:       "import.43",
  1639  		renamedPkg: "x",
  1640  		pkg:        "fmt",
  1641  		in: `package main
  1642  
  1643  import "fmt"
  1644  import "fmt"
  1645  import f "fmt"
  1646  import f "fmt"
  1647  `,
  1648  		out: `package main
  1649  
  1650  import "fmt"
  1651  import "fmt"
  1652  import f "fmt"
  1653  import f "fmt"
  1654  `,
  1655  		unchanged: true,
  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  
  1665  import (
  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  
  1677  import (
  1678  	"foo.com/a.thing"
  1679  	"foo.com/other/v2"
  1680  	"foo.com/surprise"
  1681  	"foo.com/v1"
  1682  )
  1683  `,
  1684  	},
  1685  }
  1686  
  1687  func TestDeleteImport(t *testing.T) {
  1688  	for _, test := range deleteTests {
  1689  		file := parse(t, test.name, test.in)
  1690  		var before bytes.Buffer
  1691  		ast.Fprint(&before, fset, file, nil)
  1692  		deleted := DeleteNamedImport(fset, file, test.renamedPkg, test.pkg)
  1693  		if got := print(t, test.name, file); got != test.out {
  1694  			t.Errorf("first run: %s:\ngot: %s\nwant: %s", test.name, got, test.out)
  1695  			var after bytes.Buffer
  1696  			ast.Fprint(&after, fset, file, nil)
  1697  			t.Logf("AST before:\n%s\nAST after:\n%s\n", before.String(), after.String())
  1698  		}
  1699  		if got, want := deleted, !test.unchanged; got != want {
  1700  			t.Errorf("first run: %s: deleted = %v, want %v", test.name, got, want)
  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(fset, file, test.renamedPkg, test.pkg)
  1706  		if got := print(t, test.name, file); got != test.out {
  1707  			t.Errorf("second run: %s:\ngot: %s\nwant: %s", test.name, got, test.out)
  1708  		}
  1709  		if got, want := deleted, false; got != want {
  1710  			t.Errorf("second run: %s: deleted = %v, want %v", test.name, got, want)
  1711  		}
  1712  	}
  1713  }
  1714  
  1715  func TestDeleteImportAfterAddImport(t *testing.T) {
  1716  	file := parse(t, "test", `package main
  1717  
  1718  import "os"
  1719  `)
  1720  	if got, want := AddImport(fset, file, "fmt"), true; got != want {
  1721  		t.Errorf("AddImport: got: %v, want: %v", got, want)
  1722  	}
  1723  	if got, want := DeleteImport(fset, file, "fmt"), true; got != want {
  1724  		t.Errorf("DeleteImport: got: %v, want: %v", got, want)
  1725  	}
  1726  }
  1727  
  1728  type rewriteTest struct {
  1729  	name   string
  1730  	srcPkg string
  1731  	dstPkg string
  1732  	in     string
  1733  	out    string
  1734  }
  1735  
  1736  var rewriteTests = []rewriteTest{
  1737  	{
  1738  		name:   "import.13",
  1739  		srcPkg: "utf8",
  1740  		dstPkg: "encoding/utf8",
  1741  		in: `package main
  1742  
  1743  import (
  1744  	"io"
  1745  	"os"
  1746  	"utf8" // thanks ken
  1747  )
  1748  `,
  1749  		out: `package main
  1750  
  1751  import (
  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  
  1764  import (
  1765  	"asn1"
  1766  	"crypto"
  1767  	"crypto/rsa"
  1768  	_ "crypto/sha1"
  1769  	"crypto/x509"
  1770  	"crypto/x509/pkix"
  1771  	"time"
  1772  )
  1773  
  1774  var x = 1
  1775  `,
  1776  		out: `package main
  1777  
  1778  import (
  1779  	"crypto"
  1780  	"crypto/rsa"
  1781  	_ "crypto/sha1"
  1782  	"crypto/x509"
  1783  	"crypto/x509/pkix"
  1784  	"encoding/asn1"
  1785  	"time"
  1786  )
  1787  
  1788  var x = 1
  1789  `,
  1790  	},
  1791  	{
  1792  		name:   "import.15",
  1793  		srcPkg: "url",
  1794  		dstPkg: "net/url",
  1795  		in: `package main
  1796  
  1797  import (
  1798  	"bufio"
  1799  	"net"
  1800  	"path"
  1801  	"url"
  1802  )
  1803  
  1804  var x = 1 // comment on x, not on url
  1805  `,
  1806  		out: `package main
  1807  
  1808  import (
  1809  	"bufio"
  1810  	"net"
  1811  	"net/url"
  1812  	"path"
  1813  )
  1814  
  1815  var 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  
  1824  import (
  1825  	"flag"
  1826  	"http"
  1827  	"log"
  1828  	"text/template"
  1829  )
  1830  
  1831  var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
  1832  `,
  1833  		out: `package main
  1834  
  1835  import (
  1836  	"flag"
  1837  	"log"
  1838  	"net/http"
  1839  	"text/template"
  1840  )
  1841  
  1842  var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18
  1843  `,
  1844  	},
  1845  }
  1846  
  1847  func TestRewriteImport(t *testing.T) {
  1848  	for _, test := range rewriteTests {
  1849  		file := parse(t, test.name, test.in)
  1850  		RewriteImport(fset, file, test.srcPkg, test.dstPkg)
  1851  		if got := print(t, test.name, file); got != test.out {
  1852  			t.Errorf("%s:\ngot: %s\nwant: %s", test.name, got, test.out)
  1853  		}
  1854  	}
  1855  }
  1856  
  1857  var importsTests = []struct {
  1858  	name string
  1859  	in   string
  1860  	want [][]string
  1861  }{
  1862  	{
  1863  		name: "no packages",
  1864  		in: `package foo
  1865  `,
  1866  		want: nil,
  1867  	},
  1868  	{
  1869  		name: "one group",
  1870  		in: `package foo
  1871  
  1872  import (
  1873  	"fmt"
  1874  	"testing"
  1875  )
  1876  `,
  1877  		want: [][]string{{"fmt", "testing"}},
  1878  	},
  1879  	{
  1880  		name: "four groups",
  1881  		in: `package foo
  1882  
  1883  import "C"
  1884  import (
  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  
  1905  import (
  1906  	"fmt"
  1907  	"testing"
  1908  
  1909  	"appengine"
  1910  )
  1911  import (
  1912  	"reflect"
  1913  
  1914  	"bytes"
  1915  )
  1916  `,
  1917  		want: [][]string{
  1918  			{"fmt", "testing"},
  1919  			{"appengine"},
  1920  			{"reflect"},
  1921  			{"bytes"},
  1922  		},
  1923  	},
  1924  }
  1925  
  1926  func unquote(s string) string {
  1927  	res, err := strconv.Unquote(s)
  1928  	if err != nil {
  1929  		return "could_not_unquote"
  1930  	}
  1931  	return res
  1932  }
  1933  
  1934  func TestImports(t *testing.T) {
  1935  	fset := token.NewFileSet()
  1936  	for _, test := range importsTests {
  1937  		f, err := parser.ParseFile(fset, "test.go", test.in, 0)
  1938  		if err != nil {
  1939  			t.Errorf("%s: %v", test.name, err)
  1940  			continue
  1941  		}
  1942  		var got [][]string
  1943  		for _, group := range Imports(fset, f) {
  1944  			var b []string
  1945  			for _, spec := range group {
  1946  				b = append(b, unquote(spec.Path.Value))
  1947  			}
  1948  			got = append(got, b)
  1949  		}
  1950  		if !reflect.DeepEqual(got, test.want) {
  1951  			t.Errorf("Imports(%s)=%v, want %v", test.name, got, test.want)
  1952  		}
  1953  	}
  1954  }
  1955  
  1956  var 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  		want: false,
  1968  	},
  1969  	{
  1970  		name: "import.1",
  1971  		path: "io",
  1972  		in: `package foo
  1973  
  1974  import "io"
  1975  
  1976  var _ io.Writer
  1977  `,
  1978  		want: true,
  1979  	},
  1980  	{
  1981  		name: "import.2",
  1982  		path: "io",
  1983  		in: `package foo
  1984  
  1985  import "io"
  1986  `,
  1987  		want: false,
  1988  	},
  1989  	{
  1990  		name: "import.3",
  1991  		path: "io",
  1992  		in: `package foo
  1993  
  1994  import "io"
  1995  
  1996  var io = 42
  1997  `,
  1998  		want: false,
  1999  	},
  2000  	{
  2001  		name: "import.4",
  2002  		path: "io",
  2003  		in: `package foo
  2004  
  2005  import i "io"
  2006  
  2007  var _ i.Writer
  2008  `,
  2009  		want: true,
  2010  	},
  2011  	{
  2012  		name: "import.5",
  2013  		path: "io",
  2014  		in: `package foo
  2015  
  2016  import i "io"
  2017  `,
  2018  		want: false,
  2019  	},
  2020  	{
  2021  		name: "import.6",
  2022  		path: "io",
  2023  		in: `package foo
  2024  
  2025  import i "io"
  2026  
  2027  var i = 42
  2028  var io = 42
  2029  `,
  2030  		want: false,
  2031  	},
  2032  	{
  2033  		name: "import.7",
  2034  		path: "encoding/json",
  2035  		in: `package foo
  2036  
  2037  import "encoding/json"
  2038  
  2039  var _ json.Encoder
  2040  `,
  2041  		want: true,
  2042  	},
  2043  	{
  2044  		name: "import.8",
  2045  		path: "encoding/json",
  2046  		in: `package foo
  2047  
  2048  import "encoding/json"
  2049  `,
  2050  		want: false,
  2051  	},
  2052  	{
  2053  		name: "import.9",
  2054  		path: "encoding/json",
  2055  		in: `package foo
  2056  
  2057  import "encoding/json"
  2058  
  2059  var json = 42
  2060  `,
  2061  		want: false,
  2062  	},
  2063  	{
  2064  		name: "import.10",
  2065  		path: "encoding/json",
  2066  		in: `package foo
  2067  
  2068  import j "encoding/json"
  2069  
  2070  var _ j.Encoder
  2071  `,
  2072  		want: true,
  2073  	},
  2074  	{
  2075  		name: "import.11",
  2076  		path: "encoding/json",
  2077  		in: `package foo
  2078  
  2079  import j "encoding/json"
  2080  `,
  2081  		want: false,
  2082  	},
  2083  	{
  2084  		name: "import.12",
  2085  		path: "encoding/json",
  2086  		in: `package foo
  2087  
  2088  import j "encoding/json"
  2089  
  2090  var j = 42
  2091  var json = 42
  2092  `,
  2093  		want: false,
  2094  	},
  2095  	{
  2096  		name: "import.13",
  2097  		path: "io",
  2098  		in: `package foo
  2099  
  2100  import _ "io"
  2101  `,
  2102  		want: true,
  2103  	},
  2104  	{
  2105  		name: "import.14",
  2106  		path: "io",
  2107  		in: `package foo
  2108  
  2109  import . "io"
  2110  `,
  2111  		want: true,
  2112  	},
  2113  }
  2114  
  2115  func TestUsesImport(t *testing.T) {
  2116  	fset := token.NewFileSet()
  2117  	for _, test := range usesImportTests {
  2118  		f, err := parser.ParseFile(fset, "test.go", test.in, 0)
  2119  		if err != nil {
  2120  			t.Errorf("%s: %v", test.name, err)
  2121  			continue
  2122  		}
  2123  		got := UsesImport(f, test.path)
  2124  		if got != test.want {
  2125  			t.Errorf("UsesImport(%s)=%v, want %v", test.name, got, test.want)
  2126  		}
  2127  	}
  2128  }