github.com/Johnny2210/revive@v1.0.8-0.20210625134200-febf37ccd0f5/rule/blank-imports.go (about)

     1  package rule
     2  
     3  import (
     4  	"go/ast"
     5  	"strings"
     6  
     7  	"github.com/mgechev/revive/lint"
     8  )
     9  
    10  // BlankImportsRule lints given else constructs.
    11  type BlankImportsRule struct{}
    12  
    13  // Name returns the rule name.
    14  func (r *BlankImportsRule) Name() string {
    15  	return "blank-imports"
    16  }
    17  
    18  // Apply applies the rule to given file.
    19  func (r *BlankImportsRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
    20  	if file.Pkg.IsMain() || file.IsTest() {
    21  		return nil
    22  	}
    23  
    24  	const (
    25  		message  = "a blank import should be only in a main or test package, or have a comment justifying it"
    26  		category = "imports"
    27  
    28  		embedImportPath = `"embed"`
    29  	)
    30  
    31  	var failures []lint.Failure
    32  
    33  	// The first element of each contiguous group of blank imports should have
    34  	// an explanatory comment of some kind.
    35  	for i, imp := range file.AST.Imports {
    36  		pos := file.ToPosition(imp.Pos())
    37  
    38  		if !isBlank(imp.Name) {
    39  			continue // Ignore non-blank imports.
    40  		}
    41  
    42  		if i > 0 {
    43  			prev := file.AST.Imports[i-1]
    44  			prevPos := file.ToPosition(prev.Pos())
    45  
    46  			isSubsequentBlancInAGroup := isBlank(prev.Name) && prevPos.Line+1 == pos.Line && prev.Path.Value != embedImportPath
    47  			if isSubsequentBlancInAGroup {
    48  				continue
    49  			}
    50  		}
    51  
    52  		if imp.Path.Value == embedImportPath && r.fileHasValidEmbedComment(file.AST) {
    53  			continue
    54  		}
    55  
    56  		// This is the first blank import of a group.
    57  		if imp.Doc == nil && imp.Comment == nil {
    58  			failures = append(failures, lint.Failure{Failure: message, Category: category, Node: imp, Confidence: 1})
    59  		}
    60  	}
    61  
    62  	return failures
    63  }
    64  
    65  func (r *BlankImportsRule) fileHasValidEmbedComment(fileAst *ast.File) bool {
    66  	for _, commentGroup := range fileAst.Comments {
    67  		for _, comment := range commentGroup.List {
    68  			if strings.HasPrefix(comment.Text, "//go:embed ") {
    69  				return true
    70  			}
    71  		}
    72  	}
    73  
    74  	return false
    75  }