Source file src/cmd/vendor/golang.org/x/tools/go/analysis/passes/modernize/plusbuild.go

     1  // Copyright 2025 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 modernize
     6  
     7  import (
     8  	"go/ast"
     9  	"go/parser"
    10  	"strings"
    11  
    12  	"golang.org/x/tools/go/analysis"
    13  	"golang.org/x/tools/internal/analysis/analyzerutil"
    14  	"golang.org/x/tools/internal/goplsexport"
    15  	"golang.org/x/tools/internal/versions"
    16  )
    17  
    18  var plusBuildAnalyzer = &analysis.Analyzer{
    19  	Name: "plusbuild",
    20  	Doc:  analyzerutil.MustExtractDoc(doc, "plusbuild"),
    21  	URL:  "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#plusbuild",
    22  	Run:  plusbuild,
    23  }
    24  
    25  func init() {
    26  	// Export to gopls until this is a published modernizer.
    27  	goplsexport.PlusBuildModernizer = plusBuildAnalyzer
    28  }
    29  
    30  func plusbuild(pass *analysis.Pass) (any, error) {
    31  	check := func(f *ast.File) {
    32  		if !analyzerutil.FileUsesGoVersion(pass, f, versions.Go1_18) {
    33  			return
    34  		}
    35  
    36  		// When gofmt sees a +build comment, it adds a
    37  		// preceding equivalent //go:build directive, so in
    38  		// formatted files we can assume that a +build line is
    39  		// part of a comment group that starts with a
    40  		// //go:build line and is followed by a blank line.
    41  		//
    42  		// While we cannot delete comments from an AST and
    43  		// expect consistent output in general, this specific
    44  		// case--deleting only some lines from a comment
    45  		// block--does format correctly.
    46  		for _, g := range f.Comments {
    47  			sawGoBuild := false
    48  			for _, c := range g.List {
    49  				if sawGoBuild && strings.HasPrefix(c.Text, "// +build ") {
    50  					pass.Report(analysis.Diagnostic{
    51  						Pos:     c.Pos(),
    52  						End:     c.End(),
    53  						Message: "+build line is no longer needed",
    54  						SuggestedFixes: []analysis.SuggestedFix{{
    55  							Message: "Remove obsolete +build line",
    56  							TextEdits: []analysis.TextEdit{{
    57  								Pos: c.Pos(),
    58  								End: c.End(),
    59  							}},
    60  						}},
    61  					})
    62  					break
    63  				}
    64  				if strings.HasPrefix(c.Text, "//go:build ") {
    65  					sawGoBuild = true
    66  				}
    67  			}
    68  		}
    69  	}
    70  
    71  	for _, f := range pass.Files {
    72  		check(f)
    73  	}
    74  	for _, name := range pass.IgnoredFiles {
    75  		if strings.HasSuffix(name, ".go") {
    76  			f, err := parser.ParseFile(pass.Fset, name, nil, parser.ParseComments|parser.SkipObjectResolution)
    77  			if err != nil {
    78  				continue // parse error: ignore
    79  			}
    80  			check(f)
    81  		}
    82  	}
    83  	return nil, nil
    84  }
    85  

View as plain text