Update the visibility error message to mention exports_files().

With --incompatible_no_implicit_file_export, users can get new errors in their code. Not all users are familiar with the exports_files() function, so we now mention it explicitly each time a visibility error is for a file.

RELNOTES: None.
PiperOrigin-RevId: 296179153
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/CommonPrerequisiteValidator.java b/src/main/java/com/google/devtools/build/lib/analysis/CommonPrerequisiteValidator.java
index ba9225d..6a8a511 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/CommonPrerequisiteValidator.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/CommonPrerequisiteValidator.java
@@ -19,6 +19,7 @@
 import com.google.devtools.build.lib.cmdline.PackageIdentifier;
 import com.google.devtools.build.lib.packages.Attribute;
 import com.google.devtools.build.lib.packages.FunctionSplitTransitionWhitelist;
+import com.google.devtools.build.lib.packages.InputFile;
 import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
 import com.google.devtools.build.lib.packages.OutputFile;
 import com.google.devtools.build.lib.packages.PackageGroup;
@@ -152,6 +153,11 @@
                   + "the visibility declaration of the former target if you think "
                   + "the dependency is legitimate",
               AliasProvider.describeTargetWithAliases(prerequisite, TargetMode.WITHOUT_KIND), rule);
+
+      if (prerequisite.getTarget().getTargetKind().equals(InputFile.targetKind())) {
+        errorMessage +=
+            ". To set the visibility of that source file target, use the exports_files() function";
+      }
       context.ruleError(errorMessage);
     }
   }
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/AnalysisFailureReportingTest.java b/src/test/java/com/google/devtools/build/lib/analysis/AnalysisFailureReportingTest.java
index b6d0242..3c33512 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/AnalysisFailureReportingTest.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/AnalysisFailureReportingTest.java
@@ -153,6 +153,30 @@
   }
 
   @Test
+  public void testFileVisibilityError() throws Exception {
+    scratch.file("foo/BUILD", "sh_library(name = 'foo', srcs = ['//bar:bar.sh'])");
+    scratch.file("bar/BUILD", "exports_files(['bar.sh'], visibility = ['//visibility:private'])");
+    scratch.file("bar/bar.sh");
+
+    AnalysisResult result = update(eventBus, defaultFlags().with(Flag.KEEP_GOING), "//foo");
+    assertThat(result.hasError()).isTrue();
+
+    Label topLevel = Label.parseAbsoluteUnchecked("//foo");
+    assertThat(collector.events)
+        .valuesForKey(topLevel)
+        .containsExactly(
+            new AnalysisFailedCause(
+                Label.parseAbsolute("//foo", ImmutableMap.of()),
+                toId(
+                    Iterables.getOnlyElement(result.getTopLevelTargetsWithConfigs())
+                        .getConfiguration()),
+                "in sh_library rule //foo:foo: target '//bar:bar.sh' is not visible from target "
+                    + "'//foo:foo'. Check the visibility declaration of the former target if you "
+                    + "think the dependency is legitimate. To set the visibility of that source "
+                    + "file target, use the exports_files() function"));
+  }
+
+  @Test
   public void testVisibilityErrorNoKeepGoing() throws Exception {
     scratch.file("foo/BUILD",
         "sh_library(name = 'foo', deps = ['//bar'])");