github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/stylecheck/st1001/st1001.go (about)

     1  package st1001
     2  
     3  import (
     4  	"github.com/amarpal/go-tools/analysis/code"
     5  	"github.com/amarpal/go-tools/analysis/facts/generated"
     6  	"github.com/amarpal/go-tools/analysis/lint"
     7  	"github.com/amarpal/go-tools/analysis/report"
     8  	"github.com/amarpal/go-tools/config"
     9  
    10  	"golang.org/x/tools/go/analysis"
    11  )
    12  
    13  var SCAnalyzer = lint.InitializeAnalyzer(&lint.Analyzer{
    14  	Analyzer: &analysis.Analyzer{
    15  		Name:     "ST1001",
    16  		Run:      run,
    17  		Requires: []*analysis.Analyzer{generated.Analyzer, config.Analyzer},
    18  	},
    19  	Doc: &lint.Documentation{
    20  		Title: `Dot imports are discouraged`,
    21  		Text: `Dot imports that aren't in external test packages are discouraged.
    22  
    23  The \'dot_import_whitelist\' option can be used to whitelist certain
    24  imports.
    25  
    26  Quoting Go Code Review Comments:
    27  
    28  > The \'import .\' form can be useful in tests that, due to circular
    29  > dependencies, cannot be made part of the package being tested:
    30  > 
    31  >     package foo_test
    32  > 
    33  >     import (
    34  >         "bar/testutil" // also imports "foo"
    35  >         . "foo"
    36  >     )
    37  > 
    38  > In this case, the test file cannot be in package foo because it
    39  > uses \'bar/testutil\', which imports \'foo\'. So we use the \'import .\'
    40  > form to let the file pretend to be part of package foo even though
    41  > it is not. Except for this one case, do not use \'import .\' in your
    42  > programs. It makes the programs much harder to read because it is
    43  > unclear whether a name like \'Quux\' is a top-level identifier in the
    44  > current package or in an imported package.`,
    45  		Since:   "2019.1",
    46  		Options: []string{"dot_import_whitelist"},
    47  		MergeIf: lint.MergeIfAny,
    48  	},
    49  })
    50  
    51  var Analyzer = SCAnalyzer.Analyzer
    52  
    53  func run(pass *analysis.Pass) (interface{}, error) {
    54  	for _, f := range pass.Files {
    55  	imports:
    56  		for _, imp := range f.Imports {
    57  			path := imp.Path.Value
    58  			path = path[1 : len(path)-1]
    59  			for _, w := range config.For(pass).DotImportWhitelist {
    60  				if w == path {
    61  					continue imports
    62  				}
    63  			}
    64  
    65  			if imp.Name != nil && imp.Name.Name == "." && !code.IsInTest(pass, f) {
    66  				report.Report(pass, imp, "should not use dot imports", report.FilterGenerated())
    67  			}
    68  		}
    69  	}
    70  	return nil, nil
    71  }