| // Copyright 2024 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package ast_test |
| |
| import ( |
| "go/ast" |
| "go/parser" |
| "go/token" |
| "testing" |
| ) |
| |
| func TestSortImportsUpdatesFileImportsField(t *testing.T) { |
| t.Run("one import statement", func(t *testing.T) { |
| const src = `package test |
| |
| import ( |
| "test" |
| "test" // test comment |
| ) |
| ` |
| |
| fset := token.NewFileSet() |
| f, err := parser.ParseFile(fset, "test.go", src, parser.ParseComments|parser.SkipObjectResolution) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| ast.SortImports(fset, f) |
| |
| // Check that the duplicate import spec is eliminated. |
| importDeclSpecCount := len(f.Decls[0].(*ast.GenDecl).Specs) |
| if importDeclSpecCount != 1 { |
| t.Fatalf("len(f.Decls[0].(*ast.GenDecl).Specs) = %v; want = 1", importDeclSpecCount) |
| } |
| |
| // Check that File.Imports is consistent. |
| if len(f.Imports) != 1 { |
| t.Fatalf("len(f.Imports) = %v; want = 1", len(f.Imports)) |
| } |
| }) |
| |
| t.Run("multiple import statements", func(t *testing.T) { |
| const src = `package test |
| |
| import "unsafe" |
| |
| import ( |
| "package" |
| "package" |
| ) |
| |
| import ( |
| "test" |
| "test" |
| ) |
| ` |
| |
| fset := token.NewFileSet() |
| f, err := parser.ParseFile(fset, "test.go", src, parser.ParseComments|parser.SkipObjectResolution) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| ast.SortImports(fset, f) |
| |
| // Check that three single-spec import decls remain. |
| for i := range 3 { |
| importDeclSpecCount := len(f.Decls[i].(*ast.GenDecl).Specs) |
| if importDeclSpecCount != 1 { |
| t.Fatalf("len(f.Decls[%v].(*ast.GenDecl).Specs) = %v; want = 1", i, importDeclSpecCount) |
| } |
| } |
| |
| // Check that File.Imports is consistent. |
| if len(f.Imports) != 3 { |
| t.Fatalf("len(f.Imports) = %v; want = 3", len(f.Imports)) |
| } |
| }) |
| } |
| |
| func TestIssue69183(t *testing.T) { |
| const src = `package A |
| import ( |
| "a"//a |
| "a") |
| ` |
| fset := token.NewFileSet() |
| f, err := parser.ParseFile(fset, "test.go", src, parser.ParseComments|parser.SkipObjectResolution) |
| if err != nil { |
| t.Fatal(err) |
| } |
| ast.SortImports(fset, f) // should not panic |
| } |
| |
| func TestSortImportsSameLastLine(t *testing.T) { |
| const src = `package A |
| import ( |
| "a"//a |
| "a") |
| func a() {} |
| ` |
| |
| fset := token.NewFileSet() |
| f, err := parser.ParseFile(fset, "test.go", src, parser.ParseComments|parser.SkipObjectResolution) |
| if err != nil { |
| t.Fatal(err) |
| } |
| ast.SortImports(fset, f) |
| fd := f.Decls[1].(*ast.FuncDecl) |
| fdPos := fset.Position(fd.Pos()) |
| // After SortImports, the Position of the func, should still be at Column == 1. |
| // This is related to the issue: https://go.dev/issue/69183, we were merging lines |
| // incorrectly, which caused the position to be Column = 6, Line = 4. |
| if fdPos.Column != 1 { |
| t.Errorf("invalid fdPos.Column = %v; want = 1", fdPos.Column) |
| } |
| if fdPos.Line != 5 { |
| t.Errorf("invalid fdPos.Line = %v; want = 5", fdPos.Line) |
| } |
| } |