mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-12-10 20:13:53 +00:00
255 lines
7.5 KiB
Go
255 lines
7.5 KiB
Go
/* Copyright 2017 The Bazel Authors. All rights reserved.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package golang
|
|
|
|
import (
|
|
"log"
|
|
|
|
"github.com/bazelbuild/bazel-gazelle/internal/config"
|
|
"github.com/bazelbuild/bazel-gazelle/internal/language/proto"
|
|
"github.com/bazelbuild/bazel-gazelle/internal/rule"
|
|
bzl "github.com/bazelbuild/buildtools/build"
|
|
)
|
|
|
|
func (_ *goLang) Fix(c *config.Config, f *rule.File) {
|
|
migrateLibraryEmbed(c, f)
|
|
migrateGrpcCompilers(c, f)
|
|
flattenSrcs(c, f)
|
|
squashCgoLibrary(c, f)
|
|
squashXtest(c, f)
|
|
removeLegacyProto(c, f)
|
|
removeLegacyGazelle(c, f)
|
|
}
|
|
|
|
// migrateLibraryEmbed converts "library" attributes to "embed" attributes,
|
|
// preserving comments. This only applies to Go rules, and only if there is
|
|
// no keep comment on "library" and no existing "embed" attribute.
|
|
func migrateLibraryEmbed(c *config.Config, f *rule.File) {
|
|
for _, r := range f.Rules {
|
|
if !isGoRule(r.Kind()) {
|
|
continue
|
|
}
|
|
libExpr := r.Attr("library")
|
|
if libExpr == nil || rule.ShouldKeep(libExpr) || r.Attr("embed") != nil {
|
|
continue
|
|
}
|
|
r.DelAttr("library")
|
|
r.SetAttr("embed", &bzl.ListExpr{List: []bzl.Expr{libExpr}})
|
|
}
|
|
}
|
|
|
|
// migrateGrpcCompilers converts "go_grpc_library" rules into "go_proto_library"
|
|
// rules with a "compilers" attribute.
|
|
func migrateGrpcCompilers(c *config.Config, f *rule.File) {
|
|
for _, r := range f.Rules {
|
|
if r.Kind() != "go_grpc_library" || r.ShouldKeep() || r.Attr("compilers") != nil {
|
|
continue
|
|
}
|
|
r.SetKind("go_proto_library")
|
|
r.SetAttr("compilers", []string{config.GrpcCompilerLabel})
|
|
}
|
|
}
|
|
|
|
// squashCgoLibrary removes cgo_library rules with the default name and
|
|
// merges their attributes with go_library with the default name. If no
|
|
// go_library rule exists, a new one will be created.
|
|
//
|
|
// Note that the library attribute is disregarded, so cgo_library and
|
|
// go_library attributes will be squashed even if the cgo_library was unlinked.
|
|
// MergeFile will remove unused values and attributes later.
|
|
func squashCgoLibrary(c *config.Config, f *rule.File) {
|
|
// Find the default cgo_library and go_library rules.
|
|
var cgoLibrary, goLibrary *rule.Rule
|
|
for _, r := range f.Rules {
|
|
if r.Kind() == "cgo_library" && r.Name() == config.DefaultCgoLibName && !r.ShouldKeep() {
|
|
if cgoLibrary != nil {
|
|
log.Printf("%s: when fixing existing file, multiple cgo_library rules with default name found", f.Path)
|
|
continue
|
|
}
|
|
cgoLibrary = r
|
|
continue
|
|
}
|
|
if r.Kind() == "go_library" && r.Name() == config.DefaultLibName {
|
|
if goLibrary != nil {
|
|
log.Printf("%s: when fixing existing file, multiple go_library rules with default name referencing cgo_library found", f.Path)
|
|
}
|
|
goLibrary = r
|
|
continue
|
|
}
|
|
}
|
|
|
|
if cgoLibrary == nil {
|
|
return
|
|
}
|
|
if !c.ShouldFix {
|
|
log.Printf("%s: cgo_library is deprecated. Run 'gazelle fix' to squash with go_library.", f.Path)
|
|
return
|
|
}
|
|
|
|
if goLibrary == nil {
|
|
cgoLibrary.SetKind("go_library")
|
|
cgoLibrary.SetName(config.DefaultLibName)
|
|
cgoLibrary.SetAttr("cgo", true)
|
|
return
|
|
}
|
|
|
|
if err := rule.SquashRules(cgoLibrary, goLibrary, f.Path); err != nil {
|
|
log.Print(err)
|
|
return
|
|
}
|
|
goLibrary.DelAttr("embed")
|
|
goLibrary.SetAttr("cgo", true)
|
|
cgoLibrary.Delete()
|
|
}
|
|
|
|
// squashXtest removes go_test rules with the default external name and merges
|
|
// their attributes with a go_test rule with the default internal name. If
|
|
// no internal go_test rule exists, a new one will be created (effectively
|
|
// renaming the old rule).
|
|
func squashXtest(c *config.Config, f *rule.File) {
|
|
// Search for internal and external tests.
|
|
var itest, xtest *rule.Rule
|
|
for _, r := range f.Rules {
|
|
if r.Kind() != "go_test" {
|
|
continue
|
|
}
|
|
if r.Name() == config.DefaultTestName {
|
|
itest = r
|
|
} else if r.Name() == config.DefaultXTestName {
|
|
xtest = r
|
|
}
|
|
}
|
|
|
|
if xtest == nil || xtest.ShouldKeep() || (itest != nil && itest.ShouldKeep()) {
|
|
return
|
|
}
|
|
if !c.ShouldFix {
|
|
if itest == nil {
|
|
log.Printf("%s: go_default_xtest is no longer necessary. Run 'gazelle fix' to rename to go_default_test.", f.Path)
|
|
} else {
|
|
log.Printf("%s: go_default_xtest is no longer necessary. Run 'gazelle fix' to squash with go_default_test.", f.Path)
|
|
}
|
|
return
|
|
}
|
|
|
|
// If there was no internal test, we can just rename the external test.
|
|
if itest == nil {
|
|
xtest.SetName(config.DefaultTestName)
|
|
return
|
|
}
|
|
|
|
// Attempt to squash.
|
|
if err := rule.SquashRules(xtest, itest, f.Path); err != nil {
|
|
log.Print(err)
|
|
return
|
|
}
|
|
xtest.Delete()
|
|
}
|
|
|
|
// flattenSrcs transforms srcs attributes structured as concatenations of
|
|
// lists and selects (generated from PlatformStrings; see
|
|
// extractPlatformStringsExprs for matching details) into a sorted,
|
|
// de-duplicated list. Comments are accumulated and de-duplicated across
|
|
// duplicate expressions.
|
|
func flattenSrcs(c *config.Config, f *rule.File) {
|
|
for _, r := range f.Rules {
|
|
if !isGoRule(r.Kind()) {
|
|
continue
|
|
}
|
|
oldSrcs := r.Attr("srcs")
|
|
if oldSrcs == nil {
|
|
continue
|
|
}
|
|
flatSrcs := rule.FlattenExpr(oldSrcs)
|
|
if flatSrcs != oldSrcs {
|
|
r.SetAttr("srcs", flatSrcs)
|
|
}
|
|
}
|
|
}
|
|
|
|
// removeLegacyProto removes uses of the old proto rules. It deletes loads
|
|
// from go_proto_library.bzl. It deletes proto filegroups. It removes
|
|
// go_proto_library attributes which are no longer recognized. New rules
|
|
// are generated in place of the deleted rules, but attributes and comments
|
|
// are not migrated.
|
|
func removeLegacyProto(c *config.Config, f *rule.File) {
|
|
// Don't fix if the proto mode was set to something other than the default.
|
|
pc := proto.GetProtoConfig(c)
|
|
if pc.Mode != proto.DefaultMode {
|
|
return
|
|
}
|
|
|
|
// Scan for definitions to delete.
|
|
var protoLoads []*rule.Load
|
|
for _, l := range f.Loads {
|
|
if l.Name() == "@io_bazel_rules_go//proto:go_proto_library.bzl" {
|
|
protoLoads = append(protoLoads, l)
|
|
}
|
|
}
|
|
var protoFilegroups, protoRules []*rule.Rule
|
|
for _, r := range f.Rules {
|
|
if r.Kind() == "filegroup" && r.Name() == legacyProtoFilegroupName {
|
|
protoFilegroups = append(protoFilegroups, r)
|
|
}
|
|
if r.Kind() == "go_proto_library" {
|
|
protoRules = append(protoRules, r)
|
|
}
|
|
}
|
|
if len(protoLoads)+len(protoFilegroups) == 0 {
|
|
return
|
|
}
|
|
if !c.ShouldFix {
|
|
log.Printf("%s: go_proto_library.bzl is deprecated. Run 'gazelle fix' to replace old rules.", f.Path)
|
|
return
|
|
}
|
|
|
|
// Delete legacy proto loads and filegroups. Only delete go_proto_library
|
|
// rules if we deleted a load.
|
|
for _, l := range protoLoads {
|
|
l.Delete()
|
|
}
|
|
for _, r := range protoFilegroups {
|
|
r.Delete()
|
|
}
|
|
if len(protoLoads) > 0 {
|
|
for _, r := range protoRules {
|
|
r.Delete()
|
|
}
|
|
}
|
|
}
|
|
|
|
// removeLegacyGazelle removes loads of the "gazelle" macro from
|
|
// @io_bazel_rules_go//go:def.bzl. The definition has moved to
|
|
// @bazel_gazelle//:def.bzl, and the old one will be deleted soon.
|
|
func removeLegacyGazelle(c *config.Config, f *rule.File) {
|
|
for _, l := range f.Loads {
|
|
if l.Name() == "@io_bazel_rules_go//go:def.bzl" && l.Has("gazelle") {
|
|
l.Remove("gazelle")
|
|
if l.IsEmpty() {
|
|
l.Delete()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func isGoRule(kind string) bool {
|
|
return kind == "go_library" ||
|
|
kind == "go_binary" ||
|
|
kind == "go_test" ||
|
|
kind == "go_proto_library" ||
|
|
kind == "go_grpc_library"
|
|
}
|