Source file src/go/ast/import_test.go

     1  // Copyright 2024 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 ast_test
     6  
     7  import (
     8  	"go/ast"
     9  	"go/parser"
    10  	"go/token"
    11  	"testing"
    12  )
    13  
    14  func TestSortImportsUpdatesFileImportsField(t *testing.T) {
    15  	t.Run("one import statement", func(t *testing.T) {
    16  		const src = `package test
    17  
    18  import (
    19  	"test"
    20  	"test" // test comment
    21  )
    22  `
    23  
    24  		fset := token.NewFileSet()
    25  		f, err := parser.ParseFile(fset, "test.go", src, parser.ParseComments|parser.SkipObjectResolution)
    26  		if err != nil {
    27  			t.Fatal(err)
    28  		}
    29  
    30  		ast.SortImports(fset, f)
    31  
    32  		// Check that the duplicate import spec is eliminated.
    33  		importDeclSpecCount := len(f.Decls[0].(*ast.GenDecl).Specs)
    34  		if importDeclSpecCount != 1 {
    35  			t.Fatalf("len(f.Decls[0].(*ast.GenDecl).Specs) = %v; want = 1", importDeclSpecCount)
    36  		}
    37  
    38  		// Check that File.Imports is consistent.
    39  		if len(f.Imports) != 1 {
    40  			t.Fatalf("len(f.Imports) = %v; want = 1", len(f.Imports))
    41  		}
    42  	})
    43  
    44  	t.Run("multiple import statements", func(t *testing.T) {
    45  		const src = `package test
    46  
    47  import "unsafe"
    48  
    49  import (
    50  	"package"
    51  	"package"
    52  )
    53  
    54  import (
    55  	"test"
    56  	"test"
    57  )
    58  `
    59  
    60  		fset := token.NewFileSet()
    61  		f, err := parser.ParseFile(fset, "test.go", src, parser.ParseComments|parser.SkipObjectResolution)
    62  		if err != nil {
    63  			t.Fatal(err)
    64  		}
    65  
    66  		ast.SortImports(fset, f)
    67  
    68  		// Check that three single-spec import decls remain.
    69  		for i := range 3 {
    70  			importDeclSpecCount := len(f.Decls[i].(*ast.GenDecl).Specs)
    71  			if importDeclSpecCount != 1 {
    72  				t.Fatalf("len(f.Decls[%v].(*ast.GenDecl).Specs) = %v; want = 1", i, importDeclSpecCount)
    73  			}
    74  		}
    75  
    76  		// Check that File.Imports is consistent.
    77  		if len(f.Imports) != 3 {
    78  			t.Fatalf("len(f.Imports) = %v; want = 3", len(f.Imports))
    79  		}
    80  	})
    81  }
    82  
    83  func TestIssue69183(t *testing.T) {
    84  	const src = `package A
    85  import (
    86  "a"//a
    87  "a")
    88  `
    89  	fset := token.NewFileSet()
    90  	f, err := parser.ParseFile(fset, "test.go", src, parser.ParseComments|parser.SkipObjectResolution)
    91  	if err != nil {
    92  		t.Fatal(err)
    93  	}
    94  	ast.SortImports(fset, f) // should not panic
    95  }
    96  
    97  func TestSortImportsSameLastLine(t *testing.T) {
    98  	const src = `package A
    99  import (
   100  "a"//a
   101  "a")
   102  func a() {}
   103  `
   104  
   105  	fset := token.NewFileSet()
   106  	f, err := parser.ParseFile(fset, "test.go", src, parser.ParseComments|parser.SkipObjectResolution)
   107  	if err != nil {
   108  		t.Fatal(err)
   109  	}
   110  	ast.SortImports(fset, f)
   111  	fd := f.Decls[1].(*ast.FuncDecl)
   112  	fdPos := fset.Position(fd.Pos())
   113  	// After SortImports, the Position of the func, should still be at Column == 1.
   114  	// This is related to the issue: https://go.dev/issue/69183, we were merging lines
   115  	// incorrectly, which caused the position to be Column = 6, Line = 4.
   116  	if fdPos.Column != 1 {
   117  		t.Errorf("invalid fdPos.Column = %v; want = 1", fdPos.Column)
   118  	}
   119  	if fdPos.Line != 5 {
   120  		t.Errorf("invalid fdPos.Line = %v; want = 5", fdPos.Line)
   121  	}
   122  }
   123  

View as plain text