Repository: bazelbuild/buildtools
Pull request #1053 (2022-02-21 19:04:49)

[buildifier] Add warning and fix for cfg = "host"

Yannic: /cc @susinmotion
meisterT: cc @katre 

Patch:
diff --git a/WARNINGS.md b/WARNINGS.md
index 15882b4..096aae1 100644
--- a/WARNINGS.md
+++ b/WARNINGS.md
@@ -94,6 +94,8 @@ if debug:
 
 The [Configuration](https://docs.bazel.build/versions/master/skylark/rules.html#configurations)
 `cfg = "data"` is deprecated and has no effect. Consider removing it.
+The [Configuration](https://docs.bazel.build/versions/master/skylark/rules.html#configurations)
+`cfg = "host"` is deprecated. Consider replacing it with `cfg = "exec"`.
 
 --------------------------------------------------------------------------------
 
diff --git a/warn/docs/warnings.textproto b/warn/docs/warnings.textproto
index a144e8c..a82e0bf 100644
--- a/warn/docs/warnings.textproto
+++ b/warn/docs/warnings.textproto
@@ -7,7 +7,9 @@ warnings: {
   header: "`cfg = \"data\"` for attr definitions has no effect"
   description:
     "The [Configuration](https://docs.bazel.build/versions/master/skylark/rules.html#configurations)\n"
-    "`cfg = \"data\"` is deprecated and has no effect. Consider removing it."
+    "`cfg = \"data\"` is deprecated and has no effect. Consider removing it.\n"
+    "The [Configuration](https://docs.bazel.build/versions/master/skylark/rules.html#configurations)\n"
+    "`cfg = \"host\"` is deprecated. Consider replacing it with `cfg = \"exec\"`."
   bazel_flag: "--incompatible_disallow_data_transition"
   bazel_flag_link: "https://github.com/bazelbuild/bazel/issues/6153"
   autofix: true
diff --git a/warn/warn_bazel_api.go b/warn/warn_bazel_api.go
index 8012fb5..3d74f1d 100644
--- a/warn/warn_bazel_api.go
+++ b/warn/warn_bazel_api.go
@@ -330,7 +330,7 @@ func attrConfigurationWarning(f *build.File) []*LinterFinding {
 
 	var findings []*LinterFinding
 	build.WalkPointers(f, func(expr *build.Expr, stack []build.Expr) {
-		// Find nodes that match the following pattern: attr.xxxx(..., cfg = "data", ...)
+		// Find nodes that match the following pattern: attr.xxxx(..., cfg = "data", ...) and attr.xxxx(..., cfg = "host", ...)
 		call, ok := (*expr).(*build.CallExpr)
 		if !ok {
 			return
@@ -348,15 +348,34 @@ func attrConfigurationWarning(f *build.File) []*LinterFinding {
 			return
 		}
 		value, ok := (param.RHS).(*build.StringExpr)
-		if !ok || value.Value != "data" {
+		if !ok {
 			return
 		}
+
 		newCall := *call
-		newCall.List = append(newCall.List[:i], newCall.List[i+1:]...)
+		switch value.Value {
+		case "data":
+			newCall.List = append(newCall.List[:i], newCall.List[i+1:]...)
+			findings = append(findings,
+				makeLinterFinding(param, `cfg = "data" for attr definitions has no effect and should be removed.`,
+					LinterReplacement{expr, &newCall}))
+
+		case "host": {
+			newCall.List = append([]build.Expr{}, newCall.List...)
+			newParam := newCall.List[i].Copy().(*build.AssignExpr)
+			newRHS := newParam.RHS.Copy().(*build.StringExpr)
+			newRHS.Value = "exec"
+			newParam.RHS = newRHS
+			newCall.List[i] = newParam
+			findings = append(findings,
+				makeLinterFinding(param, `cfg = "host" for attr definitions should be replaced by cfg = "exec".`,
+					LinterReplacement{expr, &newCall}))
+			}
 
-		findings = append(findings,
-			makeLinterFinding(param, `cfg = "data" for attr definitions has no effect and should be removed.`,
-				LinterReplacement{expr, &newCall}))
+		default:
+			// value not matched.
+			return
+		}
 	})
 	return findings
 }


Test patch:
diff --git a/warn/warn_bazel_api_test.go b/warn/warn_bazel_api_test.go
index 9071d60..2ebee86 100644
--- a/warn/warn_bazel_api_test.go
+++ b/warn/warn_bazel_api_test.go
@@ -23,7 +23,7 @@ import (
 	"github.com/bazelbuild/buildtools/tables"
 )
 
-func TestAttrConfigurationWarning(t *testing.T) {
+func TestAttrDataConfigurationWarning(t *testing.T) {
 	checkFindingsAndFix(t, "attr-cfg", `
 rule(
   attrs = {
@@ -31,18 +31,38 @@ rule(
   }
 )
 
-attr.label_list(mandatory = True, cfg = "host")`, `
+attr.label_list(mandatory = True, cfg = "exec")`, `
 rule(
   attrs = {
       "foo": attr.label_list(mandatory = True),
   }
 )
 
-attr.label_list(mandatory = True, cfg = "host")`,
+attr.label_list(mandatory = True, cfg = "exec")`,
 		[]string{`:3: cfg = "data" for attr definitions has no effect and should be removed.`},
 		scopeBzl)
 }
 
+func TestAttrHostConfigurationWarning(t *testing.T) {
+	checkFindingsAndFix(t, "attr-cfg", `
+rule(
+  attrs = {
+      "foo": attr.label_list(mandatory = True, cfg = "host"),
+  }
+)
+
+attr.label_list(mandatory = True, cfg = "exec")`, `
+rule(
+  attrs = {
+      "foo": attr.label_list(mandatory = True, cfg = "exec"),
+  }
+)
+
+attr.label_list(mandatory = True, cfg = "exec")`,
+		[]string{`:3: cfg = "host" for attr definitions should be replaced by cfg = "exec".`},
+		scopeBzl)
+}
+
 func TestDepsetItemsWarning(t *testing.T) {
 	checkFindings(t, "depset-items", `
 def f():