Repository: bazelbuild/buildtools (go)

Issue:
'bzl-visibility' checks fail for multiple references to the same workspace
The 'bzl-visibility' check is causing warnings if a rule uses a load statement that changes between '@//', '//' and '@workspace_name//', even if all three are pointing to the same workspace on disk. 

For example, the [bazelrules/rules_apple](https://github.com/bazelbuild/rules_apple) will fail with the following error:

```
$ buildifier.mac -lint warn ./apple/apple.bzl
./apple/apple.bzl:18: bzl-visibility: Module "@build_bazel_rules_apple//apple/internal:apple_framework_import.bzl" can only be loaded from files located inside "@build_bazel_rules_apple//apple", not from "//apple". (https://github.com/bazelbuild/buildtools/blob/master/WARNINGS.md#bzl-visibility)
```

Pull request description:
Mute false positive warnings for private .bzl files
If a private .bzl file which is allowed to be loaded from the current file is loaded using a fully quailfied path (including a repository name), buildifier shows a false positive warning for the `bzl-visibility` category.

This change makes buildifier ignore the repository name, which may mute some true positive warnings (if a file is being loaded from another repository but with a similar directory structure) but it also mutes the false positives.

Fixes #718.

Patch:
diff --git a/warn/warn_visibility.go b/warn/warn_visibility.go
index 6973a8f..8ae3eb7 100644
--- a/warn/warn_visibility.go
+++ b/warn/warn_visibility.go
@@ -28,8 +28,22 @@ func bzlVisibilityWarning(f *build.File) []*LinterFinding {
 			continue
 		}
 
+		// A load statement may use a fully qualified module name (including a
+		// repository name). Buildifier should check if the repository name refers
+		// to the current repository, but because it doesn't know the current
+		// repository name it's better to assume that it matches the repository name
+		// in the load statement: this way it may miss some usages of private .bzl
+		// files that aren't supposed to be visible, but won't show false-positive
+		// warnings in case the private file is actually allowed to be used.
+		module := load.Module.Value
+		if strings.HasPrefix(module, "@") {
+			if chunks := strings.SplitN(module, "//", 2); len(chunks) == 2 {
+				module = "//" + chunks[1]
+			}
+		}
+
 		pkg := "//" + f.Pkg // Canonical name of the package
-		chunks := internalDirectory.Split(load.Module.Value, 2)
+		chunks := internalDirectory.Split(module, 2)
 		if len(chunks) < 2 {
 			continue
 		}


Test patch:
diff --git a/warn/warn_visibility_test.go b/warn/warn_visibility_test.go
index 71f876c..b40c607 100644
--- a/warn/warn_visibility_test.go
+++ b/warn/warn_visibility_test.go
@@ -33,6 +33,25 @@ baz()
 		},
 		scopeEverywhere)
 
+	checkFindings(t, "bzl-visibility", `
+load("@repo//foo/bar/internal:module.bzl", "foo")
+load("@repo//foo/bar/private:module.bzl", "bar")
+load("@repo//foo/bar/external:module.bzl", "baz")
+load("@repo/internal:module.bzl", "qux")  # incorrect, but shouldn't cause buildifier crashes
+
+
+foo()
+bar()
+baz()
+qux()
+`,
+		[]string{
+			`:1: Module "@repo//foo/bar/internal:module.bzl" can only be loaded from files located inside "//foo/bar", not from "//test/package".`,
+			`:2: Module "@repo//foo/bar/private:module.bzl" can only be loaded from files located inside "//foo/bar", not from "//test/package".`,
+			`:4: Module "@repo/internal:module.bzl" can only be loaded from files located inside "@repo", not from "//test/package".`,
+		},
+		scopeEverywhere)
+
 	checkFindings(t, "bzl-visibility", `
 load("//test/internal/foo:module.bzl", "foo")
 load("//test/private/foo:module.bzl", "bar")
@@ -40,6 +59,17 @@ load("//test/external/foo:module.bzl", "baz")
 load("//test/internal:module.bzl", "foo")
 load("//test/private:module.bzl", "bar")
 load("//test/external:module.bzl", "baz")
+`,
+		[]string{},
+		scopeEverywhere)
+
+	checkFindings(t, "bzl-visibility", `
+load("@repo//test/internal/foo:module.bzl", "foo")
+load("@repo//test/private/foo:module.bzl", "bar")
+load("@repo//test/external/foo:module.bzl", "baz")
+load("@repo//test/internal:module.bzl", "foo")
+load("@repo//test/private:module.bzl", "bar")
+load("@repo//test/external:module.bzl", "baz")
 `,
 		[]string{},
 		scopeEverywhere)