Repository: bazelbuild/buildtools
Pull request #1329 (2025-01-30 10:58:28)

Fix load placement for files with docstring and copyright header
Also add missing setup calls for other tests.

fmeum: @vladmos Could you create another patch release after the merge?

Patch:
diff --git a/warn/warn_bazel_api.go b/warn/warn_bazel_api.go
index a1c3c23..707a848 100644
--- a/warn/warn_bazel_api.go
+++ b/warn/warn_bazel_api.go
@@ -158,10 +158,10 @@ func insertLoad(f *build.File, module string, symbols []string) *LinterReplaceme
 	i := 0
 	for i = range f.Stmt {
 		stmt := f.Stmt[i]
-		_, isComment := stmt.(*build.CommentBlock)
-		_, isString := stmt.(*build.StringExpr)
-		isDocString := isString && i == 0
-		if !isComment && !isDocString {
+		if _, isComment := stmt.(*build.CommentBlock); isComment {
+			continue
+		}
+		if _, isDocString := stmt.(*build.StringExpr); !isDocString {
 			// Insert a nil statement here
 			break
 		}


Test patch:
diff --git a/warn/warn_bazel_api_test.go b/warn/warn_bazel_api_test.go
index 4074a9b..2d7b6e2 100644
--- a/warn/warn_bazel_api_test.go
+++ b/warn/warn_bazel_api_test.go
@@ -774,6 +774,8 @@ def macro():
 }
 
 func TestNativeShBinaryWarning(t *testing.T) {
+	defer setUpFileReader(nil)()
+
 	checkFindingsAndFix(t, "native-sh-binary", `
 """My file"""
 
@@ -799,6 +801,8 @@ sh_binary()
 }
 
 func TestNativeShLibraryWarning(t *testing.T) {
+	defer setUpFileReader(nil)()
+
 	checkFindingsAndFix(t, "native-sh-library", `
 """My file"""
 
@@ -824,6 +828,8 @@ sh_library()
 }
 
 func TestNativeShTestWarning(t *testing.T) {
+	defer setUpFileReader(nil)()
+
 	checkFindingsAndFix(t, "native-sh-test", `
 """My file"""
 
@@ -848,6 +854,68 @@ sh_test()
 		scopeBzl|scopeBuild)
 }
 
+func TestNativeWarningLoadPlacedAfterFileDocstringWithComment(t *testing.T) {
+	defer setUpFileReader(nil)()
+
+	checkFindingsAndFix(t, "native-sh-binary,native-java-binary", `
+# Copyright 2020 Google LLC
+#
+# 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
+#
+#     https://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.
+
+"""My file"""
+
+def macro():
+    native.sh_binary()
+    native.java_binary()
+
+java_binary()
+sh_binary()
+`, `
+# Copyright 2020 Google LLC
+#
+# 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
+#
+#     https://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.
+
+"""My file"""
+
+load("@rules_java//java:java_binary.bzl", "java_binary")
+load("@rules_shell//shell:sh_binary.bzl", "sh_binary")
+
+def macro():
+    sh_binary()
+    java_binary()
+
+java_binary()
+sh_binary()
+`,
+		[]string{
+			fmt.Sprintf(`:18: Function "sh_binary" is not global anymore and needs to be loaded from "@rules_shell//shell:sh_binary.bzl".`),
+			fmt.Sprintf(`:19: Function "java_binary" is not global anymore and needs to be loaded from "@rules_java//java:java_binary.bzl".`),
+			fmt.Sprintf(`:21: Function "java_binary" is not global anymore and needs to be loaded from "@rules_java//java:java_binary.bzl".`),
+			fmt.Sprintf(`:22: Function "sh_binary" is not global anymore and needs to be loaded from "@rules_shell//shell:sh_binary.bzl".`),
+		},
+		scopeBzl|scopeBuild)
+}
+
 func TestKeywordParameters(t *testing.T) {
 	checkFindingsAndFix(t, "keyword-positional-params", `
 foo(key = value)